Esempio n. 1
0
static bNode *node_group_make_from_selected(const bContext *C, bNodeTree *ntree, const char *ntype, const char *ntreetype)
{
	Main *bmain = CTX_data_main(C);
	bNode *gnode;
	bNodeTree *ngroup;
	float min[2], max[2];
	int totselect;
	
	totselect = node_get_selected_minmax(ntree, NULL, min, max);
	/* don't make empty group */
	if (totselect == 0)
		return NULL;
	
	/* new nodetree */
	ngroup = ntreeAddTree(bmain, "NodeGroup", ntreetype);
	
	/* make group node */
	gnode = nodeAddNode(C, ntree, ntype);
	gnode->id = (ID *)ngroup;
	
	gnode->locx = 0.5f * (min[0] + max[0]);
	gnode->locy = 0.5f * (min[1] + max[1]);
	
	node_group_make_insert_selected(C, ntree, gnode);

	/* update of the tree containing the group instance node */
	ntree->update |= NTREE_UPDATE_NODES;

	return gnode;
}
Esempio n. 2
0
/* /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */
static MatItem *mat_livedb_add_mat_element(Main *bmain, bContext *C, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, MatItem **_item, char* file_path, float x_pos, float *y_pos)
{
    MatItem          *ptr;
    MatItem          *item = *_item;
    char             tex_file_name[1024];

    bNodeSocket             *sock;

    switch (item->type) {
        case MAT_LDB_VALUE_TYPE_EMPTY: {
            *_item = (MatItem*)((char*)item + item->size);
            break;
        }
        case MAT_LDB_VALUE_TYPE_FLINK: {
            ptr = (MatItem*) ((char*)item - item->uint_vector[0]);
            mat_livedb_add_mat_element(bmain, C, ntree, node_to, 0, &ptr, file_path, 0, 0);

            *_item = (MatItem*)((char*)item + item->size);
            break;
        }
        case MAT_LDB_VALUE_TYPE_NLINK: {
            bNode *linked_node = *((bNode**) ((MatItem*)((char*)item - item->uint_vector[0]))->data);

            connect_node(bmain, ntree, linked_node, node_to, sock_to);

            *_item = (MatItem*)((char*)item + item->size);
            break;
        }
        case MAT_LDB_VALUE_TYPE_NODE: {
            if(sock_to->type == SOCK_FLOAT && sock_to->default_value && !strcmp(item->data, "ShaderNodeOctFloatTex")) {
                item = (MatItem*)((char*)item + item->size);

                ((bNodeSocketValueFloat*)sock_to->default_value)->value = item->float_vector[0];

                *_item = (MatItem*)((char*)item + item->size);
            }
            else if(sock_to->type == SOCK_RGBA && sock_to->default_value && !strcmp(item->data, "ShaderNodeOctRGBSpectrumTex")) {
                item = (MatItem*)((char*)item + item->size);

                ((bNodeSocketValueRGBA*)sock_to->default_value)->value[0] = item->float_vector[0];
                ((bNodeSocketValueRGBA*)sock_to->default_value)->value[1] = item->float_vector[1];
                ((bNodeSocketValueRGBA*)sock_to->default_value)->value[2] = item->float_vector[2];
                ((bNodeSocketValueRGBA*)sock_to->default_value)->value[3] = item->float_vector[3];

                *_item = (MatItem*)((char*)item + item->size);
            }
            else {
                float   cur_y_pos;
                int     node_height     = U.widget_unit;
                bool    childs_present  = false;
                bNode   *node_fr        = nodeAddNode(C, ntree, item->data);

                connect_node(bmain, ntree, node_fr, node_to, sock_to);

                *_item = (MatItem*)((char*)item + item->size);
                ptr = *_item;

                *((bNode**)item->data) = node_fr;

                if(node_fr->type == SH_NODE_OCT_IMAGE_TEX || node_fr->type == SH_NODE_OCT_FLOAT_IMAGE_TEX || node_fr->type == SH_NODE_OCT_ALPHA_IMAGE_TEX) {
                    mat_livedb_add_mat_element(bmain, C, ntree, node_fr, 0, &ptr, file_path, 0, 0);
                    node_height += (U.widget_unit * 2.5);
                }

                node_fr->locx = x_pos - node_fr->width - LDB_NODES_H_GAP;
                node_fr->locy = cur_y_pos = *y_pos;

                for (sock = node_fr->inputs.first; sock; sock = sock->next) {
                    if(!sock) continue;
                    if(!childs_present) childs_present = true;
                    node_height += U.widget_unit;

                    mat_livedb_add_mat_element(bmain, C, ntree, node_fr, sock, &ptr, file_path, node_fr->locx, &cur_y_pos);
                }

                if(node_fr->type == SH_NODE_OCT_GRADIENT_TEX) {
                    mat_livedb_add_mat_element(bmain, C, ntree, node_fr, 0, &ptr, file_path, 0, 0);
                    node_height += (U.widget_unit * 2.5);
                }

                *_item = ptr;

                *y_pos -= (node_height + LDB_NODES_V_GAP);
                if(childs_present) *y_pos = (*y_pos < cur_y_pos ? *y_pos : cur_y_pos);
            }
            break;
        }
        case MAT_LDB_VALUE_TYPE_INT:
            if(sock_to->default_value)
                ((bNodeSocketValueInt*)sock_to->default_value)->value = item->int_vector[0];

            *_item = (MatItem*)((char*)item + item->size);
            break;
        case MAT_LDB_VALUE_TYPE_INT2:
            if(sock_to->default_value) {
                ((bNodeSocketValueVector*)sock_to->default_value)->value[0] = item->int_vector[0];
                ((bNodeSocketValueVector*)sock_to->default_value)->value[1] = item->int_vector[1];
            }

            *_item = (MatItem*)((char*)item + item->size);
            break;
        case MAT_LDB_VALUE_TYPE_INT3:
            if(sock_to->default_value) {
                ((bNodeSocketValueVector*)sock_to->default_value)->value[0] = item->int_vector[0];
                ((bNodeSocketValueVector*)sock_to->default_value)->value[1] = item->int_vector[1];
                ((bNodeSocketValueVector*)sock_to->default_value)->value[2] = item->int_vector[2];
            }

            *_item = (MatItem*)((char*)item + item->size);
            break;
        case MAT_LDB_VALUE_TYPE_INT4:
            if(sock_to->default_value) {
                ((bNodeSocketValueRGBA*)sock_to->default_value)->value[0] = item->int_vector[0];
                ((bNodeSocketValueRGBA*)sock_to->default_value)->value[1] = item->int_vector[1];
                ((bNodeSocketValueRGBA*)sock_to->default_value)->value[2] = item->int_vector[2];
                ((bNodeSocketValueRGBA*)sock_to->default_value)->value[3] = item->int_vector[3];
            }

            *_item = (MatItem*)((char*)item + item->size);
            break;
        case MAT_LDB_VALUE_TYPE_FLOAT:
            if(sock_to->default_value)
                ((bNodeSocketValueFloat*)sock_to->default_value)->value = item->float_vector[0];

            *_item = (MatItem*)((char*)item + item->size);
            break;
        case MAT_LDB_VALUE_TYPE_FLOAT2:
            if(sock_to->default_value) {
                ((bNodeSocketValueVector*)sock_to->default_value)->value[0] = item->float_vector[0];
                ((bNodeSocketValueVector*)sock_to->default_value)->value[1] = item->float_vector[1];
            }

            *_item = (MatItem*)((char*)item + item->size);
            break;
        case MAT_LDB_VALUE_TYPE_FLOAT3:
            if(sock_to->default_value) {
                ((bNodeSocketValueVector*)sock_to->default_value)->value[0] = item->float_vector[0];
                ((bNodeSocketValueVector*)sock_to->default_value)->value[1] = item->float_vector[1];
                ((bNodeSocketValueVector*)sock_to->default_value)->value[2] = item->float_vector[2];
            }

            *_item = (MatItem*)((char*)item + item->size);
            break;
        case MAT_LDB_VALUE_TYPE_FLOAT4:
            if(sock_to->default_value) {
                ((bNodeSocketValueRGBA*)sock_to->default_value)->value[0] = item->float_vector[0];
                ((bNodeSocketValueRGBA*)sock_to->default_value)->value[1] = item->float_vector[1];
                ((bNodeSocketValueRGBA*)sock_to->default_value)->value[2] = item->float_vector[2];
                ((bNodeSocketValueRGBA*)sock_to->default_value)->value[3] = item->float_vector[3];
            }

            *_item = (MatItem*)((char*)item + item->size);
            break;
        case MAT_LDB_VALUE_TYPE_BOOL:
            if(sock_to->default_value)
                ((bNodeSocketValueBoolean*)sock_to->default_value)->value = item->int_vector[0];

            *_item = (MatItem*)((char*)item + item->size);
            break;
        case MAT_LDB_VALUE_TYPE_STRING:
            if(sock_to->default_value)
                strcpy(((bNodeSocketValueString*)sock_to->default_value)->value, item->data);

            *_item = (MatItem*)((char*)item + item->size);
            break;
        case MAT_LDB_VALUE_TYPE_COLOR:
            if(sock_to->default_value) {
                ((bNodeSocketValueRGBA*)sock_to->default_value)->value[0] = item->float_vector[0];
                ((bNodeSocketValueRGBA*)sock_to->default_value)->value[1] = item->float_vector[1];
                ((bNodeSocketValueRGBA*)sock_to->default_value)->value[2] = item->float_vector[2];
                ((bNodeSocketValueRGBA*)sock_to->default_value)->value[3] = item->float_vector[3];
            }

            *_item = (MatItem*)((char*)item + item->size);
            break;
        case MAT_LDB_VALUE_TYPE_FILE: {
            char* file_name;
            FILE *file;
            struct Image *ima = (struct Image*)node_to->id;

            file_name = item->data + sizeof(uint32_t);

            if(file_name[0]) {
                strcpy(tex_file_name, file_path);
                strcat(tex_file_name, file_name);

                file = BLI_fopen(tex_file_name, "rb");
                if(!file) {
                    file = BLI_fopen(tex_file_name, "wb");
                    if(file) {
                        if(!fwrite(item->data + sizeof(uint32_t) + strlen(file_name) + 1, *((uint32_t*)item->data), 1, file)) {
                        }
                        fclose(file);
                    }
                }
                else fclose(file);
            }
            else tex_file_name[0] = 0;

            if(!ima)
                node_to->id = (struct ID*)BKE_image_load_exists(tex_file_name);

            *_item = (MatItem*)((char*)item + item->size);
            break;
        }
        case MAT_LDB_VALUE_TYPE_RAMP: {
            char* file_name;
            FILE *file;
            struct ColorBand *coba = (struct ColorBand*)node_to->storage;

            RampItem *ramp_item = (RampItem*)item->data;

            if(coba && ramp_item->pos_cnt > 1) {
                int i;
                coba->tot = ramp_item->pos_cnt;
                for(i = 0; i < ramp_item->pos_cnt; ++i) {
                    coba->data[i].pos   = ramp_item->pos_data[i * 4 + 0];
                    coba->data[i].r     = ramp_item->pos_data[i * 4 + 1];
                    coba->data[i].g     = ramp_item->pos_data[i * 4 + 2];
                    coba->data[i].b     = ramp_item->pos_data[i * 4 + 3];
                    coba->data[i].a     = 1.0;
                }
            }

            *_item = (MatItem*)((char*)item + item->size);
            break;
        }
        default:
            break;
    }
    return *_item;
} /* mat_livedb_add_mat_element */
Esempio n. 3
0
bNode *node_group_make_from_selected(bNodeTree *ntree)
{
    bNodeLink *link, *linkn;
    bNode *node, *gnode, *nextn;
    bNodeTree *ngroup;
    bNodeSocket *gsock;
    ListBase anim_basepaths = {NULL, NULL};
    float min[2], max[2];
    int totnode=0;
    bNodeTemplate ntemp;

    INIT_MINMAX2(min, max);

    /* is there something to group? also do some clearing */
    for(node= ntree->nodes.first; node; node= node->next) {
        if(node->flag & NODE_SELECT) {
            /* no groups in groups */
            if(node->type==NODE_GROUP)
                return NULL;
            DO_MINMAX2( (&node->locx), min, max);
            totnode++;
        }
        node->done= 0;
    }
    if(totnode==0) return NULL;

    /* check if all connections are OK, no unselected node has both
    	inputs and outputs to a selection */
    for(link= ntree->links.first; link; link= link->next) {
        if(link->fromnode && link->tonode && link->fromnode->flag & NODE_SELECT)
            link->tonode->done |= 1;
        if(link->fromnode && link->tonode && link->tonode->flag & NODE_SELECT)
            link->fromnode->done |= 2;
    }

    for(node= ntree->nodes.first; node; node= node->next) {
        if((node->flag & NODE_SELECT)==0)
            if(node->done==3)
                break;
    }
    if(node)
        return NULL;

    /* OK! new nodetree */
    ngroup= ntreeAddTree("NodeGroup", ntree->type, NODE_GROUP);

    /* move nodes over */
    for(node= ntree->nodes.first; node; node= nextn) {
        nextn= node->next;
        if(node->flag & NODE_SELECT) {
            /* keep track of this node's RNA "base" path (the part of the pat identifying the node)
             * if the old nodetree has animation data which potentially covers this node
             */
            if (ntree->adt) {
                PointerRNA ptr;
                char *path;

                RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
                path = RNA_path_from_ID_to_struct(&ptr);

                if (path)
                    BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
            }

            /* change node-collection membership */
            BLI_remlink(&ntree->nodes, node);
            BLI_addtail(&ngroup->nodes, node);

            node->locx-= 0.5f*(min[0]+max[0]);
            node->locy-= 0.5f*(min[1]+max[1]);
        }
    }

    /* move animation data over */
    if (ntree->adt) {
        LinkData *ld, *ldn=NULL;

        BKE_animdata_separate_by_basepath(&ntree->id, &ngroup->id, &anim_basepaths);

        /* paths + their wrappers need to be freed */
        for (ld = anim_basepaths.first; ld; ld = ldn) {
            ldn = ld->next;

            MEM_freeN(ld->data);
            BLI_freelinkN(&anim_basepaths, ld);
        }
    }

    /* make group node */
    ntemp.type = NODE_GROUP;
    ntemp.ngroup = ngroup;
    gnode= nodeAddNode(ntree, &ntemp);
    gnode->locx= 0.5f*(min[0]+max[0]);
    gnode->locy= 0.5f*(min[1]+max[1]);

    /* relink external sockets */
    for(link= ntree->links.first; link; link= linkn) {
        linkn= link->next;

        if(link->fromnode && link->tonode && (link->fromnode->flag & link->tonode->flag & NODE_SELECT)) {
            BLI_remlink(&ntree->links, link);
            BLI_addtail(&ngroup->links, link);
        }
        else if(link->tonode && (link->tonode->flag & NODE_SELECT)) {
            gsock = node_group_expose_socket(ngroup, link->tosock, SOCK_IN);
            link->tosock->link = nodeAddLink(ngroup, NULL, gsock, link->tonode, link->tosock);
            link->tosock = node_group_add_extern_socket(ntree, &gnode->inputs, SOCK_IN, gsock);
            link->tonode = gnode;
        }
        else if(link->fromnode && (link->fromnode->flag & NODE_SELECT)) {
            /* search for existing group node socket */
            for (gsock=ngroup->outputs.first; gsock; gsock=gsock->next)
                if (gsock->link && gsock->link->fromsock==link->fromsock)
                    break;
            if (!gsock) {
                gsock = node_group_expose_socket(ngroup, link->fromsock, SOCK_OUT);
                gsock->link = nodeAddLink(ngroup, link->fromnode, link->fromsock, NULL, gsock);
                link->fromsock = node_group_add_extern_socket(ntree, &gnode->outputs, SOCK_OUT, gsock);
            }
            else
                link->fromsock = node_group_find_output(gnode, gsock);
            link->fromnode = gnode;
        }
    }

    ngroup->update |= NTREE_UPDATE;
    ntreeUpdateTree(ngroup);
    ntree->update |= NTREE_UPDATE_NODES|NTREE_UPDATE_LINKS;
    ntreeUpdateTree(ntree);

    return gnode;
}
Esempio n. 4
0
/* /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */
static void get_material_startjob(void *customdata, short *stop, short *do_update, float *progress)
{
    Main            *bmain;
    bContext        *C;
    bNodeTree       *ntree;
    MatItem         *items;
    uint32_t        buf_size;
    GetMaterialJob  *mj = customdata;

    mj->stop        = stop;
    mj->do_update   = do_update;
    mj->progress    = progress;

    ntree   = mj->ntree;
    bmain   = mj->bmain;
    C       = mj->C;

    *progress = 0.1f;

    items = mat_livedb_get_material(mj->address, mj->mat_id, &buf_size);

    *progress = 0.9f;

    if(items) {
        bNode       *node, *next;
        MatItem     *cur_item = items;
        bNode       *node_to;
        bNodeSocket *sock_to;
        char        file_path[FILE_MAX];
        float       cur_y_pos = 0;

        /* Remove all existing nodes */
        ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
        for (node = ntree->nodes.first; node; node = next) {
            next = node->next;
            /* check id user here, nodeFreeNode is called for free dbase too */
            if (node->id) node->id->us--;
            nodeFreeNode(ntree, node);
        }
        ntreeUpdateTree(bmain, ntree);

        node_to = nodeAddNode(C, ntree, "ShaderNodeOutputMaterial");
        node_to->locx = 0;
        node_to->locy = 0;

        for (sock_to = node_to->inputs.first; sock_to; sock_to = sock_to->next) {
            if(!sock_to || strcmp(sock_to->name, "Surface")) continue;
            break;
        }

        /* create file path */
        if(!strlen(G.main->name)) {
            char *cur_path = (char*)BKE_appdir_folder_id_create(BLENDER_USER_DATAFILES, 0);
            strcpy(file_path, cur_path);
            strcat(file_path, "/livedb/");
        }
        else {
            BLI_strncpy(file_path, "//livedb/", sizeof(file_path));
            BLI_path_abs(file_path, G.main->name);
        }
        strcat(file_path, mj->address);
        strcat(file_path, "/textures/");
        BLI_path_native_slash(file_path);
        BLI_dir_create_recursive(file_path);

        mat_livedb_add_mat_element(bmain, C, ntree, node_to, sock_to, &cur_item, file_path, 0, &cur_y_pos);

        ED_node_tree_update(C);
        ED_node_tag_update_nodetree(bmain, ntree, 0);

        MEM_freeN(items);
    }

    *do_update  = 1;
    *stop       = 0;
    *progress   = 1.0f;

    return;
} /* get_material_job() */
Esempio n. 5
0
/* add new node connected to this socket, or replace an existing one */
static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, bNodeTemplate *ntemp, int sock_num)
{
	bNode *node_from;
	bNodeSocket *sock_from;
	bNode *node_prev = NULL;

	/* unlink existing node */
	if (sock_to->link) {
		node_prev = sock_to->link->fromnode;
		nodeRemLink(ntree, sock_to->link);
	}

	/* find existing node that we can use */
	for (node_from=ntree->nodes.first; node_from; node_from=node_from->next)
		if (node_from->type == ntemp->type)
			break;

	if (node_from)
		if (!(node_from->inputs.first == NULL && !(node_from->typeinfo->flag & NODE_OPTIONS)))
			node_from = NULL;

	if (node_prev && node_prev->type == ntemp->type &&
		(ntemp->type != NODE_GROUP || node_prev->id == &ntemp->ngroup->id)) {
		/* keep the previous node if it's the same type */
		node_from = node_prev;
	}
	else if (!node_from) {
		node_from= nodeAddNode(ntree, ntemp);
		node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
		node_from->locy = node_to->locy;

		if (node_from->id)
			id_us_plus(node_from->id);
	}

	nodeSetActive(ntree, node_from);

	/* add link */
	sock_from = BLI_findlink(&node_from->outputs, sock_num);
	nodeAddLink(ntree, node_from, sock_from, node_to, sock_to);

	/* copy input sockets from previous node */
	if (node_prev && node_from != node_prev) {
		bNodeSocket *sock_prev, *sock_from;

		for (sock_prev=node_prev->inputs.first; sock_prev; sock_prev=sock_prev->next) {
			for (sock_from=node_from->inputs.first; sock_from; sock_from=sock_from->next) {
				if (nodeCountSocketLinks(ntree, sock_from) >= sock_from->limit)
					continue;
				
				if (strcmp(sock_prev->name, sock_from->name) == 0 && sock_prev->type == sock_from->type) {
					bNodeLink *link = sock_prev->link;

					if (link && link->fromnode) {
						nodeAddLink(ntree, link->fromnode, link->fromsock, node_from, sock_from);
						nodeRemLink(ntree, link);
					}

					node_socket_free_default_value(sock_from->type, sock_from->default_value);
					sock_from->default_value = node_socket_make_default_value(sock_from->type);
					node_socket_copy_default_value(sock_from->type, sock_from->default_value, sock_prev->default_value);
				}
			}
		}

		/* also preserve mapping for texture nodes */
		if (node_from->typeinfo->nclass == NODE_CLASS_TEXTURE &&
		    node_prev->typeinfo->nclass == NODE_CLASS_TEXTURE)
		{
			memcpy(node_from->storage, node_prev->storage, sizeof(NodeTexBase));
		}

		/* remove node */
		node_remove_linked(ntree, node_prev);
	}

	nodeUpdate(ntree, node_from);
	nodeUpdate(ntree, node_to);
	ntreeUpdateTree(ntree);

	ED_node_generic_update(bmain, ntree, node_to);
}