Exemplo n.º 1
0
// does copy_fcurve...
void make_local_action(bAction *act)
{
	tMakeLocalActionContext mlac = {act, NULL, 0, 0};
	Main *bmain= G.main;
	
	if (act->id.lib==NULL) 
		return;
	
	// XXX: double-check this; it used to be just single-user check, but that was when fake-users were still default
	if ((act->id.flag & LIB_FAKEUSER) && (act->id.us<=1)) {
		act->id.lib= NULL;
		act->id.flag= LIB_LOCAL;
		new_id(&bmain->action, (ID *)act, NULL);
		return;
	}
	
	BKE_animdata_main_cb(bmain, make_localact_init_cb, &mlac);
	
	if (mlac.local && mlac.lib==0) {
		act->id.lib= NULL;
		act->id.flag= LIB_LOCAL;
		//make_local_action_channels(act);
		new_id(&bmain->action, (ID *)act, NULL);
	}
	else if (mlac.local && mlac.lib) {
		mlac.actn= copy_action(act);
		mlac.actn->id.us= 0;
		
		BKE_animdata_main_cb(bmain, make_localact_apply_cb, &mlac);
	}
}
Exemplo n.º 2
0
static int act_new_exec(bContext *C, wmOperator *UNUSED(op))
{
	PointerRNA ptr, idptr;
	PropertyRNA *prop;

	/* hook into UI */
	uiIDContextProperty(C, &ptr, &prop);
	
	if (prop) {
		bAction *action=NULL, *oldact=NULL;
		PointerRNA oldptr;
		
		/* create action - the way to do this depends on whether we've got an
		 * existing one there already, in which case we make a copy of it
		 * (which is useful for "versioning" actions within the same file)
		 */
		oldptr = RNA_property_pointer_get(&ptr, prop);
		oldact = (bAction *)oldptr.id.data;
		
		if (oldact && GS(oldact->id.name)==ID_AC) {
			/* make a copy of the existing action */
			action= copy_action(oldact);
		}
		else {
			/* just make a new (empty) action */
			action= add_empty_action("Action");
		}
		
		/* when creating new ID blocks, use is already 1 (fake user), 
		 * but RNA pointer use also increases user, so this compensates it 
		 */
		action->id.us--;
		
		RNA_id_pointer_create(&action->id, &idptr);
		RNA_property_pointer_set(&ptr, prop, idptr);
		RNA_property_update(C, &ptr, prop);
	}
	
	/* set notifier that keyframes have changed */
	WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
	
	return OPERATOR_FINISHED;
}
Exemplo n.º 3
0
int id_copy(ID *id, ID **newid, int test)
{
	if(!test) *newid= NULL;

	/* conventions:
	 * - make shallow copy, only this ID block
	 * - id.us of the new ID is set to 1 */
	switch(GS(id->name)) {
		case ID_SCE:
			return 0; /* can't be copied from here */
		case ID_LI:
			return 0; /* can't be copied from here */
		case ID_OB:
			if(!test) *newid= (ID*)copy_object((Object*)id);
			return 1;
		case ID_ME:
			if(!test) *newid= (ID*)copy_mesh((Mesh*)id);
			return 1;
		case ID_CU:
			if(!test) *newid= (ID*)copy_curve((Curve*)id);
			return 1;
		case ID_MB:
			if(!test) *newid= (ID*)copy_mball((MetaBall*)id);
			return 1;
		case ID_MA:
			if(!test) *newid= (ID*)copy_material((Material*)id);
			return 1;
		case ID_TE:
			if(!test) *newid= (ID*)copy_texture((Tex*)id);
			return 1;
		case ID_IM:
			if(!test) *newid= (ID*)copy_image((Image*)id);
			return 1;
		case ID_LT:
			if(!test) *newid= (ID*)copy_lattice((Lattice*)id);
			return 1;
		case ID_LA:
			if(!test) *newid= (ID*)copy_lamp((Lamp*)id);
			return 1;
		case ID_SPK:
			if(!test) *newid= (ID*)copy_speaker((Speaker*)id);
			return 1;
		case ID_CA:
			if(!test) *newid= (ID*)copy_camera((Camera*)id);
			return 1;
		case ID_IP:
			return 0; /* deprecated */
		case ID_KE:
			if(!test) *newid= (ID*)copy_key((Key*)id);
			return 1;
		case ID_WO:
			if(!test) *newid= (ID*)copy_world((World*)id);
			return 1;
		case ID_SCR:
			return 0; /* can't be copied from here */
		case ID_VF:
			return 0; /* not implemented */
		case ID_TXT:
			if(!test) *newid= (ID*)copy_text((Text*)id);
			return 1;
		case ID_SCRIPT:
			return 0; /* deprecated */
		case ID_SO:
			return 0; /* not implemented */
		case ID_GR:
			if(!test) *newid= (ID*)copy_group((Group*)id);
			return 1;
		case ID_AR:
			if(!test) *newid= (ID*)copy_armature((bArmature*)id);
			return 1;
		case ID_AC:
			if(!test) *newid= (ID*)copy_action((bAction*)id);
			return 1;
		case ID_NT:
			if(!test) *newid= (ID*)ntreeCopyTree((bNodeTree*)id);
			return 1;
		case ID_BR:
			if(!test) *newid= (ID*)copy_brush((Brush*)id);
			return 1;
		case ID_PA:
			if(!test) *newid= (ID*)psys_copy_settings((ParticleSettings*)id);
			return 1;
		case ID_WM:
			return 0; /* can't be copied from here */
		case ID_GD:
			return 0; /* not implemented */
	}
	
	return 0;
}
Exemplo n.º 4
0
/* returns 1 if its OK */
int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
{
    bNodeLink *link, *linkn;
    bNode *node, *nextn;
    bNodeTree *ngroup, *wgroup;
    ListBase anim_basepaths = {NULL, NULL};

    ngroup= (bNodeTree *)gnode->id;
    if(ngroup==NULL) return 0;

    /* clear new pointers, set in copytree */
    for(node= ntree->nodes.first; node; node= node->next)
        node->new_node= NULL;

    /* wgroup is a temporary copy of the NodeTree we're merging in
     *	- all of wgroup's nodes are transferred across to their new home
     *	- ngroup (i.e. the source NodeTree) is left unscathed
     */
    wgroup= ntreeCopyTree(ngroup);

    /* add the nodes into the ntree */
    for(node= wgroup->nodes.first; node; node= nextn) {
        nextn= node->next;

        /* 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 (wgroup->adt) {
            PointerRNA ptr;
            char *path;

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

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

        /* migrate node */
        BLI_remlink(&wgroup->nodes, node);
        BLI_addtail(&ntree->nodes, node);

        node->locx+= gnode->locx;
        node->locy+= gnode->locy;

        node->flag |= NODE_SELECT;
    }

    /* restore external links to and from the gnode */
    for(link= ntree->links.first; link; link= link->next) {
        if (link->fromnode==gnode) {
            if (link->fromsock->groupsock) {
                bNodeSocket *gsock= link->fromsock->groupsock;
                if (gsock->link) {
                    if (gsock->link->fromnode) {
                        /* NB: using the new internal copies here! the groupsock pointer still maps to the old tree */
                        link->fromnode = (gsock->link->fromnode ? gsock->link->fromnode->new_node : NULL);
                        link->fromsock = gsock->link->fromsock->new_sock;
                    }
                    else {
                        /* group output directly maps to group input */
                        bNodeSocket *insock= node_group_find_input(gnode, gsock->link->fromsock);
                        if (insock->link) {
                            link->fromnode = insock->link->fromnode;
                            link->fromsock = insock->link->fromsock;
                        }
                    }
                }
                else {
                    /* copy the default input value from the group socket default to the external socket */
                    convert_socket_value(gsock, link->tosock);
                }
            }
        }
    }
    /* remove internal output links, these are not used anymore */
    for(link=wgroup->links.first; link; link= linkn) {
        linkn = link->next;
        if (!link->tonode)
            nodeRemLink(wgroup, link);
    }
    /* restore links from internal nodes */
    for(link= wgroup->links.first; link; link= link->next) {
        /* indicates link to group input */
        if (!link->fromnode) {
            /* NB: can't use find_group_node_input here,
             * because gnode sockets still point to the old tree!
             */
            bNodeSocket *insock;
            for (insock= gnode->inputs.first; insock; insock= insock->next)
                if (insock->groupsock->new_sock == link->fromsock)
                    break;
            if (insock->link) {
                link->fromnode = insock->link->fromnode;
                link->fromsock = insock->link->fromsock;
            }
            else {
                /* copy the default input value from the group node socket default to the internal socket */
                convert_socket_value(insock, link->tosock);
                nodeRemLink(wgroup, link);
            }
        }
    }

    /* add internal links to the ntree */
    for(link= wgroup->links.first; link; link= linkn) {
        linkn= link->next;
        BLI_remlink(&wgroup->links, link);
        BLI_addtail(&ntree->links, link);
    }

    /* and copy across the animation */
    if (wgroup->adt) {
        LinkData *ld, *ldn=NULL;
        bAction *waction;

        /* firstly, wgroup needs to temporary dummy action that can be destroyed, as it shares copies */
        waction = wgroup->adt->action = copy_action(wgroup->adt->action);

        /* now perform the moving */
        BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->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);
        }

        /* free temp action too */
        free_libblock(&G.main->action, waction);
    }

    /* delete the group instance. this also removes old input links! */
    nodeFreeNode(ntree, gnode);

    /* free the group tree (takes care of user count) */
    free_libblock(&G.main->nodetree, wgroup);

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

    return 1;
}