diff options
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_DerivedMesh.h | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_depsgraph.h | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_node.h | 50 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_scene.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 135 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/anim_sys.c | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/cdderivedmesh.c | 80 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/depsgraph.c | 125 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh.c | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/node.c | 73 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 13 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 16 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/subsurf_ccg.c | 150 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/world.c | 16 |
14 files changed, 650 insertions, 33 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 5e403849289..0c5dc32f6d8 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -324,6 +324,14 @@ struct DerivedMesh { float t), void *userData); + /* Draw all faces with materials + * o setMaterial is called for every different material nr + * o setFace is called to verify if a face must be hidden + */ + void (*drawMappedFacesMat)(DerivedMesh *dm, + void (*setMaterial)(void *userData, int, void *attribs), + int (*setFace)(void *userData, int index), void *userData); + /* Release reference to the DerivedMesh. This function decides internally * if the DerivedMesh will be freed, or cached for later use. */ void (*release)(DerivedMesh *dm); diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h index 59b7712a5a4..0b0637fb42a 100644 --- a/source/blender/blenkernel/BKE_depsgraph.h +++ b/source/blender/blenkernel/BKE_depsgraph.h @@ -120,6 +120,12 @@ void DAG_ids_flush_update(struct Main *bmain, int time); void DAG_id_tag_update(struct ID *id, short flag); /* flush all tagged updates */ void DAG_ids_flush_tagged(struct Main *bmain); + /* check and clear ID recalc flags */ +void DAG_ids_check_recalc(struct Main *bmain); +void DAG_ids_clear_recalc(struct Main *bmain); + /* test if any of this id type is tagged for update */ +void DAG_id_type_tag(struct Main *bmain, short idtype); +int DAG_id_type_tagged(struct Main *bmain, short idtype); /* (re)-create dependency graph for armature pose */ void DAG_pose_sort(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index a819a464d3f..3ba6cd3793e 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -83,6 +83,7 @@ typedef struct bNodeSocketTemplate { float val1, val2, val3, val4; /* default alloc value for inputs */ float min, max; PropertySubType subtype; + int flag; /* after this line is used internal only */ struct bNodeSocket *sock; /* used to hold verified socket */ @@ -130,7 +131,7 @@ typedef struct bNodeType { char name[32]; float width, minwidth, maxwidth; float height, minheight, maxheight; - short nclass, flag; + short nclass, flag, compatibility; /* templates for static sockets */ bNodeSocketTemplate *inputs, *outputs; @@ -230,8 +231,13 @@ typedef struct bNodeType { #define NODE_CLASS_PARTICLES 25 #define NODE_CLASS_TRANSFORM 30 #define NODE_CLASS_COMBINE 31 +#define NODE_CLASS_SHADER 40 #define NODE_CLASS_LAYOUT 100 +/* nodetype->compatibility */ +#define NODE_OLD_SHADING 1 +#define NODE_NEW_SHADING 2 + /* enum values for input/output */ #define SOCK_IN 1 #define SOCK_OUT 2 @@ -343,6 +349,7 @@ struct bNode *nodeGetActive(struct bNodeTree *ntree); struct bNode *nodeGetActiveID(struct bNodeTree *ntree, short idtype); int nodeSetActiveID(struct bNodeTree *ntree, short idtype, struct ID *id); void nodeClearActiveID(struct bNodeTree *ntree, short idtype); +struct bNode *nodeGetActiveTexture(struct bNodeTree *ntree); void nodeUpdate(struct bNodeTree *ntree, struct bNode *node); int nodeUpdateID(struct bNodeTree *ntree, struct ID *id); @@ -388,6 +395,7 @@ void node_type_exec_new(struct bNodeType *ntype, void (*newexecfunc)(void *data, int thread, struct bNode *, void *nodedata, struct bNodeStack **, struct bNodeStack **)); void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out)); void node_type_gpu_ext(struct bNodeType *ntype, int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node, void *nodedata, struct GPUNodeStack *in, struct GPUNodeStack *out)); +void node_type_compatibility(struct bNodeType *ntype, short compatibility); /* ************** COMMON NODES *************** */ @@ -432,7 +440,7 @@ struct ShadeResult; #define SH_NODE_RGBTOBW 105 #define SH_NODE_TEXTURE 106 #define SH_NODE_NORMAL 107 -#define SH_NODE_GEOMETRY 108 +#define SH_NODE_GEOM 108 #define SH_NODE_MAPPING 109 #define SH_NODE_CURVE_VEC 110 #define SH_NODE_CURVE_RGB 111 @@ -447,6 +455,44 @@ struct ShadeResult; #define SH_NODE_HUE_SAT 122 #define NODE_DYNAMIC 123 +#define SH_NODE_OUTPUT_MATERIAL 124 +#define SH_NODE_OUTPUT_WORLD 125 +#define SH_NODE_OUTPUT_LAMP 126 +#define SH_NODE_FRESNEL 127 +#define SH_NODE_MIX_SHADER 128 +#define SH_NODE_ATTRIBUTE 129 +#define SH_NODE_BACKGROUND 130 +#define SH_NODE_BSDF_ANISOTROPIC 131 +#define SH_NODE_BSDF_DIFFUSE 132 +#define SH_NODE_BSDF_GLOSSY 133 +#define SH_NODE_BSDF_GLASS 134 +#define SH_NODE_BSDF_TRANSLUCENT 137 +#define SH_NODE_BSDF_TRANSPARENT 138 +#define SH_NODE_BSDF_VELVET 139 +#define SH_NODE_EMISSION 140 +#define SH_NODE_GEOMETRY 141 +#define SH_NODE_LIGHT_PATH 142 +#define SH_NODE_TEX_IMAGE 143 +#define SH_NODE_TEX_NOISE 144 +#define SH_NODE_TEX_SKY 145 +#define SH_NODE_TEX_BLEND 146 +#define SH_NODE_TEX_VORONOI 147 +#define SH_NODE_TEX_MAGIC 148 +#define SH_NODE_TEX_MARBLE 149 +#define SH_NODE_TEX_CLOUDS 150 +#define SH_NODE_TEX_WOOD 151 +#define SH_NODE_TEX_MUSGRAVE 152 +#define SH_NODE_TEX_STUCCI 153 +#define SH_NODE_TEX_DISTNOISE 154 +#define SH_NODE_TEX_COORD 155 +#define SH_NODE_ADD_SHADER 156 +#define SH_NODE_TEX_ENVIRONMENT 157 +#define SH_NODE_OUTPUT_TEXTURE 158 +#define SH_NODE_HOLDOUT 159 +#define SH_NODE_BLEND_WEIGHT 160 +#define SH_NODE_VOLUME_TRANSPARENT 161 +#define SH_NODE_VOLUME_ISOTROPIC 162 + /* custom defines options for Material node */ #define SH_NODE_MAT_DIFF 1 #define SH_NODE_MAT_SPEC 2 diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 5c214b2892a..4806a288cee 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -88,6 +88,8 @@ int scene_check_setscene(struct Main *bmain, struct Scene *sce); float BKE_curframe(struct Scene *scene); void scene_update_tagged(struct Main *bmain, struct Scene *sce); +void scene_clear_tagged(struct Main *bmain, struct Scene *sce); + void scene_update_for_newframe(struct Main *bmain, struct Scene *sce, unsigned int lay); void scene_add_render_layer(struct Scene *sce); @@ -98,6 +100,8 @@ int get_render_child_particle_number(struct RenderData *r, int num); int get_render_shadow_samples(struct RenderData *r, int samples); float get_render_aosss_error(struct RenderData *r, float error); +int scene_use_new_shading_nodes(struct Scene *scene); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 0c99735f73e..3882d2e4e88 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1123,6 +1123,140 @@ static void emDM_drawFacesGLSL(DerivedMesh *dm, dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); } +static void emDM_drawMappedFacesMat(DerivedMesh *dm, + void (*setMaterial)(void *userData, int, void *attribs), + int (*setFace)(void *userData, int index), void *userData) +{ + EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; + EditMesh *em= emdm->em; + float (*vertexCos)[3]= emdm->vertexCos; + float (*vertexNos)[3]= emdm->vertexNos; + EditVert *eve; + EditFace *efa; + DMVertexAttribs attribs= {{{0}}}; + GPUVertexAttribs gattribs; + int i, b, matnr, new_matnr; + + matnr = -1; + + /* always use smooth shading even for flat faces, else vertex colors wont interpolate */ + glShadeModel(GL_SMOOTH); + + for (i=0,eve=em->verts.first; eve; eve= eve->next) + eve->tmp.l = (intptr_t) i++; + +#define PASSATTRIB(efa, eve, vert) { \ + if(attribs.totorco) { \ + float *orco = attribs.orco.array[eve->tmp.l]; \ + if(attribs.orco.glTexco) \ + glTexCoord3fv(orco); \ + else \ + glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \ + } \ + for(b = 0; b < attribs.tottface; b++) { \ + MTFace *_tf = (MTFace*)((char*)efa->data + attribs.tface[b].emOffset); \ + if(attribs.tface[b].glTexco) \ + glTexCoord2fv(_tf->uv[vert]); \ + else \ + glVertexAttrib2fvARB(attribs.tface[b].glIndex, _tf->uv[vert]); \ + } \ + for(b = 0; b < attribs.totmcol; b++) { \ + MCol *cp = (MCol*)((char*)efa->data + attribs.mcol[b].emOffset); \ + GLubyte col[4]; \ + col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \ + glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \ + } \ + if(attribs.tottang) { \ + float *tang = attribs.tang.array[i*4 + vert]; \ + glVertexAttrib4fvARB(attribs.tang.glIndex, tang); \ + } \ +} + + for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) { + int drawSmooth= (efa->flag & ME_SMOOTH); + + /* face hiding */ + if(setFace && !setFace(userData, i)) + continue; + + /* material */ + new_matnr = efa->mat_nr + 1; + if(new_matnr != matnr) { + setMaterial(userData, matnr = new_matnr, &gattribs); + DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); + } + + /* face */ + glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); + if (!drawSmooth) { + if(vertexCos) glNormal3fv(emdm->faceNos[i]); + else glNormal3fv(efa->n); + + PASSATTRIB(efa, efa->v1, 0); + if(vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); + else glVertex3fv(efa->v1->co); + + PASSATTRIB(efa, efa->v2, 1); + if(vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); + else glVertex3fv(efa->v2->co); + + PASSATTRIB(efa, efa->v3, 2); + if(vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); + else glVertex3fv(efa->v3->co); + + if(efa->v4) { + PASSATTRIB(efa, efa->v4, 3); + if(vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); + else glVertex3fv(efa->v4->co); + } + } else { + PASSATTRIB(efa, efa->v1, 0); + if(vertexCos) { + glNormal3fv(vertexNos[(int) efa->v1->tmp.l]); + glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); + } + else { + glNormal3fv(efa->v1->no); + glVertex3fv(efa->v1->co); + } + + PASSATTRIB(efa, efa->v2, 1); + if(vertexCos) { + glNormal3fv(vertexNos[(int) efa->v2->tmp.l]); + glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); + } + else { + glNormal3fv(efa->v2->no); + glVertex3fv(efa->v2->co); + } + + PASSATTRIB(efa, efa->v3, 2); + if(vertexCos) { + glNormal3fv(vertexNos[(int) efa->v3->tmp.l]); + glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); + } + else { + glNormal3fv(efa->v3->no); + glVertex3fv(efa->v3->co); + } + + if(efa->v4) { + PASSATTRIB(efa, efa->v4, 3); + if(vertexCos) { + glNormal3fv(vertexNos[(int) efa->v4->tmp.l]); + glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); + } + else { + glNormal3fv(efa->v4->no); + glVertex3fv(efa->v4->co); + } + } + } + glEnd(); + } +#undef PASSATTRIB +} + static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) { EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; @@ -1429,6 +1563,7 @@ DerivedMesh *editmesh_get_derived(EditMesh *em, float (*vertexCos)[3]) emdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL; emdm->dm.drawFacesTex = emDM_drawFacesTex; emdm->dm.drawFacesGLSL = emDM_drawFacesGLSL; + emdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat; emdm->dm.drawUVEdges = emDM_drawUVEdges; emdm->dm.release = emDM_release; diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 13abf18e20c..981c20d6165 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -43,9 +43,11 @@ #include "BLI_utildefines.h" #include "DNA_anim_types.h" +#include "DNA_lamp_types.h" #include "DNA_material_types.h" #include "DNA_scene_types.h" #include "DNA_texture_types.h" +#include "DNA_world_types.h" #include "BKE_animsys.h" #include "BKE_action.h" @@ -2291,7 +2293,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, Scene *scene, float ctime) EVAL_ANIM_NODETREE_IDS(main->tex.first, Tex, ADT_RECALC_ANIM); /* lamps */ - EVAL_ANIM_IDS(main->lamp.first, ADT_RECALC_ANIM); + EVAL_ANIM_NODETREE_IDS(main->lamp.first, Lamp, ADT_RECALC_ANIM); /* materials */ EVAL_ANIM_NODETREE_IDS(main->mat.first, Material, ADT_RECALC_ANIM); @@ -2331,7 +2333,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, Scene *scene, float ctime) EVAL_ANIM_IDS(main->object.first, 0); /* worlds */ - EVAL_ANIM_IDS(main->world.first, ADT_RECALC_ANIM); + EVAL_ANIM_NODETREE_IDS(main->world.first, World, ADT_RECALC_ANIM); /* scenes */ EVAL_ANIM_NODETREE_IDS(main->scene.first, Scene, ADT_RECALC_ANIM); diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 25f9f17f201..d130c7b40ac 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1351,6 +1351,85 @@ static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *at dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); } +static void cdDM_drawMappedFacesMat(DerivedMesh *dm, + void (*setMaterial)(void *userData, int, void *attribs), + int (*setFace)(void *userData, int index), void *userData) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*) dm; + GPUVertexAttribs gattribs; + DMVertexAttribs attribs; + MVert *mvert = cddm->mvert; + MFace *mf = cddm->mface; + float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL); + int a, matnr, new_matnr; + int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX); + + cdDM_update_normals_from_pbvh(dm); + + matnr = -1; + + glShadeModel(GL_SMOOTH); + + memset(&attribs, 0, sizeof(attribs)); + + glBegin(GL_QUADS); + + for(a = 0; a < dm->numFaceData; a++, mf++) { + const int smoothnormal = (mf->flag & ME_SMOOTH); + + /* material */ + new_matnr = mf->mat_nr + 1; + + if(new_matnr != matnr) { + glEnd(); + + setMaterial(userData, matnr = new_matnr, &gattribs); + DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); + + glBegin(GL_QUADS); + } + + /* skipping faces */ + if(setFace) { + orig = (index)? index[a]: a; + + if(orig != ORIGINDEX_NONE && !setFace(userData, orig)) + continue; + } + + /* smooth normal */ + if(!smoothnormal) { + if(nors) { + glNormal3fv(nors[a]); + } + else { + /* TODO ideally a normal layer should always be available */ + float nor[3]; + + if(mf->v4) + normal_quad_v3( nor,mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co); + else + normal_tri_v3( nor,mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co); + + glNormal3fv(nor); + } + } + + /* vertices */ + cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v1, 0, smoothnormal); + cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v2, 1, smoothnormal); + cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v3, 2, smoothnormal); + + if(mf->v4) + cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v4, 3, smoothnormal); + else + cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v3, 2, smoothnormal); + } + glEnd(); + + glShadeModel(GL_FLAT); +} + static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; @@ -1521,6 +1600,7 @@ static CDDerivedMesh *cdDM_create(const char *desc) dm->drawMappedFaces = cdDM_drawMappedFaces; dm->drawMappedFacesTex = cdDM_drawMappedFacesTex; dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL; + dm->drawMappedFacesMat = cdDM_drawMappedFacesMat; dm->foreachMappedVert = cdDM_foreachMappedVert; dm->foreachMappedEdge = cdDM_foreachMappedEdge; diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index c9df8a135fe..9d51571346f 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -1761,9 +1761,22 @@ void DAG_scene_sort(Main *bmain, Scene *sce) sce->recalc |= SCE_PRV_CHANGED; /* test for 3d preview */ } +static void lib_id_recalc_tag(Main *bmain, ID *id) +{ + id->flag |= LIB_ID_RECALC; + bmain->id_tag_update[id->name[0]] = 1; +} + +static void lib_id_recalc_data_tag(Main *bmain, ID *id) +{ + id->flag |= LIB_ID_RECALC_DATA; + bmain->id_tag_update[id->name[0]] = 1; +} + /* node was checked to have lasttime != curtime and is if type ID_OB */ static void flush_update_node(DagNode *node, unsigned int layer, int curtime) { + Main *bmain= G.main; DagAdjList *itA; Object *ob, *obc; int oldflag, changed=0; @@ -1789,20 +1802,24 @@ static void flush_update_node(DagNode *node, unsigned int layer, int curtime) if(itA->type & DAG_RL_OB_OB) { //printf("ob %s changes ob %s\n", ob->id.name, obc->id.name); obc->recalc |= OB_RECALC_OB; + lib_id_recalc_tag(bmain, &obc->id); } if(itA->type & DAG_RL_OB_DATA) { //printf("ob %s changes obdata %s\n", ob->id.name, obc->id.name); obc->recalc |= OB_RECALC_DATA; + lib_id_recalc_data_tag(bmain, &obc->id); } } if(ob->recalc & OB_RECALC_DATA) { if(itA->type & DAG_RL_DATA_OB) { //printf("obdata %s changes ob %s\n", ob->id.name, obc->id.name); obc->recalc |= OB_RECALC_OB; + lib_id_recalc_tag(bmain, &obc->id); } if(itA->type & DAG_RL_DATA_DATA) { //printf("obdata %s changes obdata %s\n", ob->id.name, obc->id.name); obc->recalc |= OB_RECALC_DATA; + lib_id_recalc_data_tag(bmain, &obc->id); } } if(oldflag!=obc->recalc) changed= 1; @@ -1833,6 +1850,7 @@ static void flush_update_node(DagNode *node, unsigned int layer, int curtime) if(itA->type & (DAG_RL_OB_DATA|DAG_RL_DATA_DATA)) { // printf("parent %s changes ob %s\n", ob->id.name, obc->id.name); obc->recalc |= OB_RECALC_DATA; + lib_id_recalc_data_tag(bmain, &obc->id); } } } @@ -1872,6 +1890,7 @@ static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime) /* node was checked to have lasttime != curtime , and is of type ID_OB */ static void flush_pointcache_reset(Scene *scene, DagNode *node, int curtime, int reset) { + Main *bmain= G.main; DagAdjList *itA; Object *ob; @@ -1883,8 +1902,10 @@ static void flush_pointcache_reset(Scene *scene, DagNode *node, int curtime, int ob= (Object*)(itA->node->ob); if(reset || (ob->recalc & OB_RECALC_ALL)) { - if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH)) + if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH)) { ob->recalc |= OB_RECALC_DATA; + lib_id_recalc_data_tag(bmain, &ob->id); + } flush_pointcache_reset(scene, itA->node, curtime, 1); } @@ -2001,8 +2022,10 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const sho ob= (Object*)(itA->node->ob); if(ob->recalc & OB_RECALC_ALL) { - if(BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH)) + if(BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH)) { ob->recalc |= OB_RECALC_DATA; + lib_id_recalc_data_tag(bmain, &ob->id); + } flush_pointcache_reset(sce, itA->node, lasttime, 1); } @@ -2204,6 +2227,12 @@ static void dag_object_time_update_flags(Object *ob) } } } + + if(ob->recalc & OB_RECALC_OB) + lib_id_recalc_tag(G.main, &ob->id); + if(ob->recalc & OB_RECALC_DATA) + lib_id_recalc_data_tag(G.main, &ob->id); + } /* flag all objects that need recalc, for changes in time for example */ /* do_time: make this optional because undo resets objects to their animated locations without this */ @@ -2362,6 +2391,9 @@ void DAG_on_visible_update(Main *bmain, const short do_time) DAG_scene_update_flags(bmain, scene, lay, do_time); scene->lay_updated |= lay; } + + /* hack to get objects updating on layer changes */ + DAG_id_type_tag(bmain, ID_OB); } static void dag_id_flush_update__isDependentTexture(void *userData, Object *UNUSED(ob), ID **idpoin) @@ -2408,6 +2440,7 @@ static void dag_id_flush_update(Scene *sce, ID *id) for(obt=bmain->object.first; obt; obt= obt->id.next) { if(!(ob && obt == ob) && obt->data == id) { obt->recalc |= OB_RECALC_DATA; + lib_id_recalc_data_tag(bmain, &obt->id); BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); } } @@ -2421,8 +2454,10 @@ static void dag_id_flush_update(Scene *sce, ID *id) data.is_dependent= 0; modifiers_foreachIDLink(obt, dag_id_flush_update__isDependentTexture, &data); - if (data.is_dependent) + if (data.is_dependent) { obt->recalc |= OB_RECALC_DATA; + lib_id_recalc_data_tag(bmain, &obt->id); + } /* particle settings can use the texture as well */ if(obt->particlesystem.first) { @@ -2435,7 +2470,8 @@ static void dag_id_flush_update(Scene *sce, ID *id) mtex = *mtexp; if(mtex && mtex->tex == (Tex*)id) { obt->recalc |= OB_RECALC_DATA; - + lib_id_recalc_data_tag(bmain, &obt->id); + if(mtex->mapto & PAMAP_INIT) psys->recalc |= PSYS_RECALC_RESET; if(mtex->mapto & PAMAP_CHILD) @@ -2455,6 +2491,8 @@ static void dag_id_flush_update(Scene *sce, ID *id) Key *key= ob_get_key(obt); if(!(ob && obt == ob) && ((ID *)key == id)) { obt->flag |= (OB_RECALC_OB|OB_RECALC_DATA); + lib_id_recalc_tag(bmain, &obt->id); + lib_id_recalc_data_tag(bmain, &obt->id); BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); } } @@ -2479,7 +2517,7 @@ void DAG_ids_flush_tagged(Main *bmain) ListBase *lbarray[MAX_LIBARRAY]; Scene *sce; unsigned int lay; - int a, have_tag = 0; + int a, do_flush = 0; dag_current_scene_layers(bmain, &sce, &lay); @@ -2497,23 +2535,64 @@ void DAG_ids_flush_tagged(Main *bmain) looping over all ID's in case there are no tags */ if(id && bmain->id_tag_update[id->name[0]]) { for(; id; id=id->next) { - if(id->flag & LIB_ID_RECALC) { + if(id->flag & (LIB_ID_RECALC|LIB_ID_RECALC_DATA)) { dag_id_flush_update(sce, id); - id->flag &= ~LIB_ID_RECALC; + do_flush = 1; } } + } + } + + /* flush changes to other objects */ + if(do_flush) + DAG_scene_flush_update(bmain, sce, lay, 0); +} + +void DAG_ids_check_recalc(Main *bmain) +{ + ListBase *lbarray[MAX_LIBARRAY]; + int a; + + /* loop over all ID types */ + a = set_listbasepointers(bmain, lbarray); + + while(a--) { + ListBase *lb = lbarray[a]; + ID *id = lb->first; - have_tag = 1; + /* we tag based on first ID type character to avoid + looping over all ID's in case there are no tags */ + if(id && bmain->id_tag_update[id->name[0]]) { + /* do editors update */ + dag_editors_update(bmain, NULL); + return; } } +} - if(have_tag) { - /* clear tags */ - memset(bmain->id_tag_update, 0, sizeof(bmain->id_tag_update)); - /* flush changes to other objects */ - DAG_scene_flush_update(bmain, sce, lay, 0); +void DAG_ids_clear_recalc(Main *bmain) +{ + ListBase *lbarray[MAX_LIBARRAY]; + int a; + + /* loop over all ID types */ + a = set_listbasepointers(bmain, lbarray); + + while(a--) { + ListBase *lb = lbarray[a]; + ID *id = lb->first; + + /* we tag based on first ID type character to avoid + looping over all ID's in case there are no tags */ + if(id && bmain->id_tag_update[id->name[0]]) { + for(; id; id=id->next) + if(id->flag & (LIB_ID_RECALC|LIB_ID_RECALC_DATA)) + id->flag &= ~(LIB_ID_RECALC|LIB_ID_RECALC_DATA); + } } + + memset(bmain->id_tag_update, 0, sizeof(bmain->id_tag_update)); } void DAG_id_tag_update(ID *id, short flag) @@ -2523,8 +2602,14 @@ void DAG_id_tag_update(ID *id, short flag) if(id==NULL) return; /* tag ID for update */ - id->flag |= LIB_ID_RECALC; - bmain->id_tag_update[id->name[0]] = 1; + if(flag) { + if(flag & OB_RECALC_OB) + lib_id_recalc_tag(bmain, id); + if(flag & (OB_RECALC_DATA|PSYS_RECALC)) + lib_id_recalc_data_tag(bmain, id); + } + else + lib_id_recalc_tag(bmain, id); /* flag is for objects and particle systems */ if(flag) { @@ -2556,6 +2641,16 @@ void DAG_id_tag_update(ID *id, short flag) } } +void DAG_id_type_tag(struct Main *bmain, short idtype) +{ + bmain->id_tag_update[((char*)&idtype)[0]] = 1; +} + +int DAG_id_type_tagged(Main *bmain, short idtype) +{ + return bmain->id_tag_update[((char*)&idtype)[0]]; +} + #if 0 // UNUSED /* recursively descends tree, each node only checked once */ /* node is checked to be of type object */ diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 4a8bc34cdf7..a96d3a3a217 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -194,7 +194,6 @@ Mesh *add_mesh(const char *name) me->smoothresh= 30; me->texflag= AUTOSPACE; me->flag= ME_TWOSIDED; - me->bb= unit_boundbox(); me->drawflag= ME_DRAWEDGES|ME_DRAWFACES|ME_DRAWCREASES; return me; diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 824e59a82c5..9c2b6cae751 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -43,10 +43,11 @@ #include <string.h> #include <limits.h> +#include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_node_types.h" +#include "DNA_node_types.h" #include "DNA_scene_types.h" -#include "DNA_action_types.h" #include "BLI_string.h" #include "BLI_math.h" @@ -1072,7 +1073,6 @@ void ntreeMakeLocal(bNodeTree *ntree) newtree->id.us= 0; - cd.new_id = &newtree->id; treetype->foreach_nodetree(G.main, &cd, &ntreeMakeLocal_LinkNew); } @@ -1313,11 +1313,15 @@ void nodeSetActive(bNodeTree *ntree, bNode *node) if(GS(node->id->name) == GS(tnode->id->name)) tnode->flag &= ~NODE_ACTIVE_ID; } + if(node->typeinfo->nclass == NODE_CLASS_TEXTURE) + tnode->flag &= ~NODE_ACTIVE_TEXTURE; } node->flag |= NODE_ACTIVE; if(node->id) node->flag |= NODE_ACTIVE_ID; + if(node->typeinfo->nclass == NODE_CLASS_TEXTURE) + node->flag |= NODE_ACTIVE_TEXTURE; } /* use flags are not persistant yet, groups might need different tagging, so we do it each time @@ -1751,6 +1755,10 @@ void node_type_gpu_ext(struct bNodeType *ntype, int (*gpuextfunc)(struct GPUMate ntype->gpuextfunc = gpuextfunc; } +void node_type_compatibility(struct bNodeType *ntype, short compatibility) +{ + ntype->compatibility = compatibility; +} static bNodeType *is_nodetype_registered(ListBase *typelist, int type) { @@ -1854,15 +1862,20 @@ static void registerCompositNodes(ListBase *ntypelist) static void registerShaderNodes(ListBase *ntypelist) { register_node_type_frame(ntypelist); - + register_node_type_sh_group(ntypelist); -// register_node_type_sh_forloop(ntypelist); -// register_node_type_sh_whileloop(ntypelist); - + //register_node_type_sh_forloop(ntypelist); + //register_node_type_sh_whileloop(ntypelist); + register_node_type_sh_output(ntypelist); + register_node_type_sh_material(ntypelist); + register_node_type_sh_camera(ntypelist); + register_node_type_sh_value(ntypelist); + register_node_type_sh_rgb(ntypelist); register_node_type_sh_mix_rgb(ntypelist); register_node_type_sh_valtorgb(ntypelist); register_node_type_sh_rgbtobw(ntypelist); + register_node_type_sh_texture(ntypelist); register_node_type_sh_normal(ntypelist); register_node_type_sh_geom(ntypelist); register_node_type_sh_mapping(ntypelist); @@ -1871,17 +1884,53 @@ static void registerShaderNodes(ListBase *ntypelist) register_node_type_sh_math(ntypelist); register_node_type_sh_vect_math(ntypelist); register_node_type_sh_squeeze(ntypelist); - register_node_type_sh_camera(ntypelist); - register_node_type_sh_material(ntypelist); + //register_node_type_sh_dynamic(ntypelist); register_node_type_sh_material_ext(ntypelist); - register_node_type_sh_value(ntypelist); - register_node_type_sh_rgb(ntypelist); - register_node_type_sh_texture(ntypelist); -// register_node_type_sh_dynamic(ntypelist); register_node_type_sh_invert(ntypelist); register_node_type_sh_seprgb(ntypelist); register_node_type_sh_combrgb(ntypelist); register_node_type_sh_hue_sat(ntypelist); + + register_node_type_sh_attribute(ntypelist); + register_node_type_sh_geometry(ntypelist); + register_node_type_sh_light_path(ntypelist); + register_node_type_sh_fresnel(ntypelist); + register_node_type_sh_blend_weight(ntypelist); + register_node_type_sh_tex_coord(ntypelist); + + register_node_type_sh_background(ntypelist); + register_node_type_sh_bsdf_diffuse(ntypelist); + register_node_type_sh_bsdf_glossy(ntypelist); + register_node_type_sh_bsdf_glass(ntypelist); + //register_node_type_sh_bsdf_anisotropic(ntypelist); + register_node_type_sh_bsdf_translucent(ntypelist); + register_node_type_sh_bsdf_transparent(ntypelist); + register_node_type_sh_bsdf_velvet(ntypelist); + register_node_type_sh_emission(ntypelist); + register_node_type_sh_holdout(ntypelist); + register_node_type_sh_volume_transparent(ntypelist); + register_node_type_sh_volume_isotropic(ntypelist); + register_node_type_sh_mix_shader(ntypelist); + register_node_type_sh_add_shader(ntypelist); + + register_node_type_sh_output_lamp(ntypelist); + register_node_type_sh_output_material(ntypelist); + //register_node_type_sh_output_texture(ntypelist); + register_node_type_sh_output_world(ntypelist); + + register_node_type_sh_tex_image(ntypelist); + register_node_type_sh_tex_environment(ntypelist); + register_node_type_sh_tex_sky(ntypelist); + register_node_type_sh_tex_voronoi(ntypelist); + register_node_type_sh_tex_blend(ntypelist); + register_node_type_sh_tex_magic(ntypelist); + register_node_type_sh_tex_marble(ntypelist); + register_node_type_sh_tex_clouds(ntypelist); + register_node_type_sh_tex_wood(ntypelist); + register_node_type_sh_tex_stucci(ntypelist); + register_node_type_sh_tex_noise(ntypelist); + register_node_type_sh_tex_distnoise(ntypelist); + register_node_type_sh_tex_musgrave(ntypelist); } static void registerTextureNodes(ListBase *ntypelist) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 635e0744aa1..a5edd569bc2 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -86,6 +86,7 @@ #include "BKE_mesh.h" #include "BKE_mball.h" #include "BKE_modifier.h" +#include "BKE_node.h" #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_particle.h" @@ -877,6 +878,9 @@ Lamp *copy_lamp(Lamp *la) } lan->curfalloff = curvemapping_copy(la->curfalloff); + + if(la->nodetree) + lan->nodetree= ntreeCopyTree(la->nodetree); if(la->preview) lan->preview = BKE_previewimg_copy(la->preview); @@ -903,6 +907,9 @@ Lamp *localize_lamp(Lamp *la) lan->curfalloff = curvemapping_copy(la->curfalloff); + if(la->nodetree) + lan->nodetree= ntreeLocalize(la->nodetree); + lan->preview= NULL; return lan; @@ -978,6 +985,12 @@ void free_lamp(Lamp *la) BKE_free_animdata((ID *)la); curvemapping_free(la->curfalloff); + + /* is no lib link block, but lamp extension */ + if(la->nodetree) { + ntreeFreeTree(la->nodetree); + MEM_freeN(la->nodetree); + } BKE_previewimg_free(&la->preview); BKE_icon_delete(&la->id); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 6b3786663df..d7e51bf794c 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -72,6 +72,8 @@ #include "BKE_sound.h" +#include "RE_engine.h" + //XXX #include "BIF_previewrender.h" //XXX #include "BIF_editseq.h" @@ -1009,10 +1011,17 @@ void scene_update_tagged(Main *bmain, Scene *scene) if (scene->physics_settings.quick_cache_step) BKE_ptcache_quick_cache_all(bmain, scene); + DAG_ids_check_recalc(bmain); + /* in the future this should handle updates for all datablocks, not only objects and scenes. - brecht */ } +void scene_clear_tagged(Main *bmain, Scene *UNUSED(scene)) +{ + DAG_ids_clear_recalc(bmain); +} + /* applies changes right away, does all sets too */ void scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay) { @@ -1127,3 +1136,10 @@ Base *_setlooper_base_step(Scene **sce_iter, Base *base) return NULL; } + +int scene_use_new_shading_nodes(Scene *scene) +{ + RenderEngineType *type= RE_engines_find(scene->r.engine); + return (type->flag & RE_USE_SHADING_NODES); +} + diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 115b26452e1..c8b6c030d61 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1511,6 +1511,155 @@ static void ccgDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *a dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); } + /* Only used by non-editmesh types */ +static void ccgDM_drawMappedFacesMat(DerivedMesh *dm, void (*setMaterial)(void *userData, int, void *attribs), int (*setFace)(void *userData, int index), void *userData) { + CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = ccgdm->ss; + CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); + GPUVertexAttribs gattribs; + DMVertexAttribs attribs= {{{NULL}}}; + int gridSize = ccgSubSurf_getGridSize(ss); + int gridFaces = gridSize - 1; + int edgeSize = ccgSubSurf_getEdgeSize(ss); + char *faceFlags = ccgdm->faceFlags; + int a, b, i, numVerts, matnr, new_matnr, totface; + + ccgdm_pbvh_update(ccgdm); + + matnr = -1; + +#define PASSATTRIB(dx, dy, vert) { \ + if(attribs.totorco) { \ + index = getFaceIndex(ss, f, S, x+dx, y+dy, edgeSize, gridSize); \ + if(attribs.orco.glTexco) \ + glTexCoord3fv(attribs.orco.array[index]); \ + else \ + glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]); \ + } \ + for(b = 0; b < attribs.tottface; b++) { \ + MTFace *tf = &attribs.tface[b].array[a]; \ + if(attribs.tface[b].glTexco) \ + glTexCoord2fv(tf->uv[vert]); \ + else \ + glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \ + } \ + for(b = 0; b < attribs.totmcol; b++) { \ + MCol *cp = &attribs.mcol[b].array[a*4 + vert]; \ + GLubyte col[4]; \ + col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \ + glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \ + } \ + if(attribs.tottang) { \ + float *tang = attribs.tang.array[a*4 + vert]; \ + glVertexAttrib4fvARB(attribs.tang.glIndex, tang); \ + } \ +} + + totface = ccgSubSurf_getNumFaces(ss); + for(a = 0, i = 0; i < totface; i++) { + CCGFace *f = ccgdm->faceMap[i].face; + int S, x, y, drawSmooth; + int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f)); + int origIndex = ccgDM_getFaceMapIndex(ss, f); + + numVerts = ccgSubSurf_getFaceNumVerts(f); + + /* get flags */ + if(faceFlags) { + drawSmooth = (faceFlags[index*2] & ME_SMOOTH); + new_matnr= faceFlags[index*2 + 1] + 1; + } + else { + drawSmooth = 1; + new_matnr= 1; + } + + /* material */ + if(new_matnr != matnr) { + setMaterial(userData, matnr = new_matnr, &gattribs); + DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); + } + + /* face hiding */ + if((setFace && (origIndex != ORIGINDEX_NONE) && !setFace(userData, origIndex))) { + a += gridFaces*gridFaces*numVerts; + continue; + } + + /* draw face*/ + glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT); + for (S=0; S<numVerts; S++) { + DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S); + DMGridData *vda, *vdb; + + if (drawSmooth) { + for (y=0; y<gridFaces; y++) { + glBegin(GL_QUAD_STRIP); + for (x=0; x<gridFaces; x++) { + vda = &faceGridData[(y+0)*gridSize + x]; + vdb = &faceGridData[(y+1)*gridSize + x]; + + PASSATTRIB(0, 0, 0); + glNormal3fv(vda->no); + glVertex3fv(vda->co); + + PASSATTRIB(0, 1, 1); + glNormal3fv(vdb->no); + glVertex3fv(vdb->co); + + if(x != gridFaces-1) + a++; + } + + vda = &faceGridData[(y+0)*gridSize + x]; + vdb = &faceGridData[(y+1)*gridSize + x]; + + PASSATTRIB(0, 0, 3); + glNormal3fv(vda->no); + glVertex3fv(vda->co); + + PASSATTRIB(0, 1, 2); + glNormal3fv(vdb->no); + glVertex3fv(vdb->co); + + glEnd(); + + a++; + } + } else { + glBegin(GL_QUADS); + for (y=0; y<gridFaces; y++) { + for (x=0; x<gridFaces; x++) { + float *aco = faceGridData[(y+0)*gridSize + x].co; + float *bco = faceGridData[(y+0)*gridSize + x + 1].co; + float *cco = faceGridData[(y+1)*gridSize + x + 1].co; + float *dco = faceGridData[(y+1)*gridSize + x].co; + + ccgDM_glNormalFast(aco, bco, cco, dco); + + PASSATTRIB(0, 1, 1); + glVertex3fv(dco); + PASSATTRIB(1, 1, 2); + glVertex3fv(cco); + PASSATTRIB(1, 0, 3); + glVertex3fv(bco); + PASSATTRIB(0, 0, 0); + glVertex3fv(aco); + + a++; + } + } + glEnd(); + } + } + } + +#undef PASSATTRIB + + ccgFaceIterator_free(fi); +} + + static void ccgDM_drawFacesColored(DerivedMesh *dm, int UNUSED(useTwoSided), unsigned char *col1, unsigned char *col2) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = ccgdm->ss; @@ -2379,6 +2528,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces; ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex; ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL; + ccgdm->dm.drawMappedFacesMat = ccgDM_drawMappedFacesMat; ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges; ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp; diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 5797c6c3f15..9a26cc61cfd 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -46,8 +46,10 @@ #include "BKE_library.h" #include "BKE_animsys.h" #include "BKE_global.h" -#include "BKE_main.h" #include "BKE_icons.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_node.h" void free_world(World *wrld) { @@ -63,6 +65,12 @@ void free_world(World *wrld) BKE_free_animdata((ID *)wrld); + /* is no lib link block, but world extension */ + if(wrld->nodetree) { + ntreeFreeTree(wrld->nodetree); + MEM_freeN(wrld->nodetree); + } + BKE_icon_delete((struct ID*)wrld); wrld->id.icon_id = 0; } @@ -119,6 +127,9 @@ World *copy_world(World *wrld) id_us_plus((ID *)wrldn->mtex[a]->tex); } } + + if(wrld->nodetree) + wrldn->nodetree= ntreeCopyTree(wrld->nodetree); if(wrld->preview) wrldn->preview = BKE_previewimg_copy(wrld->preview); @@ -143,6 +154,9 @@ World *localize_world(World *wrld) } } + if(wrld->nodetree) + wrldn->nodetree= ntreeLocalize(wrld->nodetree); + wrldn->preview= NULL; return wrldn; |