Beispiel #1
0
ValueNode_Bone::BoneSet
ValueNode_Bone::get_bones_affected_by(ValueNode::Handle value_node)
{
	BoneSet ret;
	set<const Node*> seen, current_nodes, new_nodes;
	int generation = 0;
	bool debug(false);

	if (getenv("SYNFIG_DEBUG_SUITABLE_PARENTS"))
		debug = true;

	if (debug) printf("getting bones affected by %lx %s\n", uintptr_t(value_node.get()), value_node->get_string().c_str());

	// initialise current_nodes with the node we're editing
	current_nodes.insert(value_node.get());
	do
	{
		generation++;
		if (debug) printf("generation %d has %zd nodes\n", generation, current_nodes.size());

		int count = 0;
		// loop through current_nodes
		for (set<const Node*>::iterator iter = current_nodes.begin(); iter != current_nodes.end(); iter++, count++)
		{
			// loop through the parents of each node in current_nodes
			set<Node*> node_parents((*iter)->parent_set);
			if (debug) printf("%s:%d node %d %lx (%s) has %zd parents\n",
							  __FILE__, __LINE__, count, uintptr_t(*iter), (*iter)->get_string().c_str(), node_parents.size());
			int count2 = 0;
			for (set<Node*>::iterator iter2 = node_parents.begin(); iter2 != node_parents.end(); iter2++, count2++)
			{
				Node* node(*iter2);
				// if (debug) printf("%s:%d parent %d: %lx (%s)\n", __FILE__, __LINE__, count2, uintptr_t(node), node->get_string().c_str());
				// for each parent we've not already seen
				if (!seen.count(node))
				{
					// note that we've seen it now
					seen.insert(node);
					// add it to the list of new nodes to loop though in the next iteration
					new_nodes.insert(node);
					// and if it's a ValueNode_Bone, add it to the set to be returned
					if (dynamic_cast<ValueNode_Bone*>(node))
						ret.insert(dynamic_cast<ValueNode_Bone*>(node));
				}
			}
		}
		current_nodes = new_nodes;
		new_nodes.clear();
	} while (current_nodes.size());

	if (debug) printf("%s:%d got %zd affected bones\n", __FILE__, __LINE__, ret.size());
	return ret;
}
Beispiel #2
0
bool
LinkableValueNode::set_link(int i,ValueNode::Handle x)
{
	ValueNode::Handle previous(get_link(i));

	if(set_link_vfunc(i,x))
	{
		// Fix 2412072: remove the previous link from the parent_set unless one of the other links is also
		// using it when we convert a value to 'switch', both 'on' and 'off' are linked to the same valuenode
		// if we then disconnect one of the two, the one we disconnect is set to be a new valuenode_const
		// and the previously shared value is removed from the parent set even though the other is still
		// using it
		if(previous)
		{
			int size = link_count(), index;
			for (index=0; index < size; ++index)
			{
				if (i == index) continue;
				if (get_link(index) == previous)
					break;
			}
			if (index == size)
				remove_child(previous.get());
		}
		add_child(x.get());

		if(!x->is_exported() && get_parent_canvas())
		{
			x->set_parent_canvas(get_parent_canvas());
		}
		changed();
		return true;
	}
	return false;
}
Beispiel #3
0
void
ValueNode_StaticList::add(const ValueNode::Handle &value_node, int index) // line 470
{
	if(index<0 || index>=(int)list.size())
	{
		if (getenv("SYNFIG_DEBUG_BONE_REFCOUNT"))
			printf("%s:%d vvv adding valuenode to end of static list\n", __FILE__, __LINE__);

		list.push_back(value_node);

		if (getenv("SYNFIG_DEBUG_BONE_REFCOUNT"))
			printf("%s:%d ^^^ done adding valuenode\n", __FILE__, __LINE__);
	}
	else
	{
		if (getenv("SYNFIG_DEBUG_BONE_REFCOUNT"))
			printf("%s:%d vvv inserting valuenode into static list at %d\n", __FILE__, __LINE__, index);

		list.insert(list.begin()+index,value_node);

		if (getenv("SYNFIG_DEBUG_BONE_REFCOUNT"))
			printf("%s:%d ^^^ done inserting valuenode\n", __FILE__, __LINE__);
	}

	add_child(value_node.get());
	//changed();

	if(get_parent_canvas())
		get_parent_canvas()->signal_value_node_child_added()(this,value_node);
	else if(get_root_canvas() && get_parent_canvas())
		get_root_canvas()->signal_value_node_child_added()(this,value_node);
}
Beispiel #4
0
bool
ValueNodeList::erase(ValueNode::Handle value_node)
{
	assert(value_node);

	iterator iter;

	for(iter=begin();iter!=end();++iter)
		if(value_node.get()==iter->get())
		{
			std::list<ValueNode::RHandle>::erase(iter);
			if(PlaceholderValueNode::Handle::cast_dynamic(value_node))
				placeholder_count_--;
			return true;
		}
	return false;
}
Beispiel #5
0
bool
Layer::connect_dynamic_param(const String& param, etl::loose_handle<ValueNode> value_node)
{
	if (!value_node) return disconnect_dynamic_param(param);

	ValueNode::Handle previous;
	DynamicParamList::iterator i = dynamic_param_list_.find(param);
	if (i != dynamic_param_list_.end()) previous = i->second;

	if (previous == value_node)
		return true;

	String param_noref = param;
	dynamic_param_list_[param]=ValueNode::Handle(value_node);

	if (previous)
	{
		// fix 2353284: if two parameters in the same layer are
		// connected to the same valuenode and we disconnect one of
		// them, the parent-child relationship for the remaining
		// connection was being deleted.  now we search the parameter
		// list to see if another parameter uses the same valuenode
		DynamicParamList::const_iterator iter;
		for (iter = dynamic_param_list().begin(); iter != dynamic_param_list().end(); iter++)
			if (iter->second == previous)
				break;
		if (iter == dynamic_param_list().end())
			remove_child(previous.get());
	}

	add_child(value_node.get());
	if(!value_node->is_exported() && get_canvas())
		value_node->set_parent_canvas(get_canvas());

	dynamic_param_changed(param);
	changed();
	return true;
}
void
ValueNode_DynamicList::add(const ValueNode::Handle &value_node, int index)
{
	ListEntry list_entry(value_node);
	list_entry.timing_info.size();

	if(index<0 || index>=(int)list.size())
	{
		list.push_back(list_entry);
	}
	else
	{
		list.insert(list.begin()+index,list_entry);
	}

	add_child(value_node.get());
	reindex();
	//changed();

	if(get_parent_canvas())
		get_parent_canvas()->signal_value_node_child_added()(this,value_node);
	else if(get_root_canvas() && get_parent_canvas())
		get_root_canvas()->signal_value_node_child_added()(this,value_node);
}
Beispiel #7
0
ValueNode_Bone::BoneSet
ValueNode_Bone::get_possible_parent_bones(ValueNode::Handle value_node)
{
	BoneSet ret;
	bool debug(false);

	if (getenv("SYNFIG_DEBUG_SUITABLE_PARENTS"))
		debug = true;

	if (debug) printf("%s:%d which bones can be parents of %lx (%s)\n", __FILE__, __LINE__, uintptr_t(value_node.get()), value_node->get_string().c_str());

	// which bones are we currently editing the parent of - it can be more than one due to linking
	ValueNode_Bone::BoneSet affected_bones(ValueNode_Bone::get_bones_affected_by(value_node));
	if (debug) printf("%s:%d got %zd affected bones\n", __FILE__, __LINE__, affected_bones.size());
	Canvas::LooseHandle canvas(value_node->get_root_canvas());
	if (debug) printf("%s:%d canvas %lx\n", __FILE__, __LINE__, uintptr_t(canvas.get()));
	for (ValueNode_Bone::BoneSet::iterator iter = affected_bones.begin(); iter != affected_bones.end(); iter++)
	{
		if (!canvas)
		{
			canvas = (*iter)->get_root_canvas();
			printf("%s:%d root canvas %lx\n", __FILE__, __LINE__, uintptr_t((*iter)->get_root_canvas().get()));
			printf("%s:%d parent canvas %lx\n", __FILE__, __LINE__, uintptr_t((*iter)->get_parent_canvas().get()));
			printf("%s:%d ancestor canvas %lx\n", __FILE__, __LINE__, uintptr_t((*iter)->get_non_inline_ancestor_canvas().get()));

		}
		if (canvas != (*iter)->get_root_canvas())
			warning("%s:%d multiple root canvases in affected bones: %lx and %lx", __FILE__, __LINE__,
					uintptr_t(canvas.get()), uintptr_t((*iter)->get_root_canvas().get()));
	}

	BoneMap bone_map(canvas_map[canvas]);

	// loop through all the bones that exist
	for (ValueNode_Bone::BoneMap::const_iterator iter=bone_map.begin(); iter!=bone_map.end(); iter++)
	{
		ValueNode_Bone::Handle bone_value_node(iter->second);

		// if the bone would be affected by our editing, skip it - it would cause a loop if the user selected it
		if (affected_bones.count(bone_value_node.get()))
			continue;

		// loop through the list of bones referenced by this bone's parent link;
		// if any of them would be affected by editing the cell, don't offer this bone in the menu
		{
			ValueNode_Bone::BoneSet parents(ValueNode_Bone::get_bones_referenced_by(bone_value_node->get_link("parent")));

			ValueNode_Bone::BoneSet::iterator iter;
			for (iter = parents.begin(); iter != parents.end(); iter++)
				if (affected_bones.count(iter->get()))
					break;
			if (iter == parents.end())
				ret.insert(bone_value_node);
		}
	}

	if (debug) printf("%s:%d returning %zd possible parents\n", __FILE__, __LINE__, ret.size());
	return ret;
}
Beispiel #8
0
ValueNode_Bone::BoneSet
ValueNode_Bone::get_bones_referenced_by(ValueNode::Handle value_node, bool recursive)
{
	// printf("%s:%d rec = %d\n", __FILE__, __LINE__,recursive);
	BoneSet ret;
	if (!value_node)
	{
		printf("%s:%d failed?\n", __FILE__, __LINE__);
		assert(0);
		return ret;
	}

	// if it's a ValueNode_Const
	if (ValueNode_Const::Handle value_node_const = ValueNode_Const::Handle::cast_dynamic(value_node))
	{
		ValueBase value_node(value_node_const->get_value());
		if (value_node.get_type() == type_bone_valuenode)
			if (ValueNode_Bone::Handle bone = value_node.get(ValueNode_Bone::Handle()))
			{
				// do we want to check for bone references in other bone fields or just 'parent'?
				if (recursive)
				{
					// printf("%s:%d rec\n", __FILE__, __LINE__);
					ret = get_bones_referenced_by(bone, recursive);
					// ret = get_bones_referenced_by(bone->get_link("parent"), recursive);
				}
				if (!bone->is_root())
					ret.insert(bone);
			}
		return ret;
	}

	// if it's a ValueNode_Animated
	if (ValueNode_Animated::Handle value_node_animated = ValueNode_Animated::Handle::cast_dynamic(value_node))
	{
		// ValueNode_Animated::Handle ret = ValueNode_Animated::create(type_bone_object);
		ValueNode_Animated::WaypointList list(value_node_animated->waypoint_list());
		for (ValueNode_Animated::WaypointList::iterator iter = list.begin(); iter != list.end(); iter++)
		{
//			printf("%s:%d getting bones from waypoint\n", __FILE__, __LINE__);
			BoneSet ret2(get_bones_referenced_by(iter->get_value_node(), recursive));
			ret.insert(ret2.begin(), ret2.end());
//			printf("added %d bones from waypoint to get %d\n", int(ret2.size()), int(ret.size()));
		}
//		printf("returning %d bones\n", int(ret.size()));
		return ret;
	}

	// if it's a LinkableValueNode
	if (LinkableValueNode::Handle linkable_value_node = LinkableValueNode::Handle::cast_dynamic(value_node))
	{
		for (int i = 0; i < linkable_value_node->link_count(); i++)
		{
			BoneSet ret2(get_bones_referenced_by(linkable_value_node->get_link(i), recursive));
			ret.insert(ret2.begin(), ret2.end());
		}
		return ret;
	}

	if (PlaceholderValueNode::Handle linkable_value_node = PlaceholderValueNode::Handle::cast_dynamic(value_node))
	{
		// todo: while loading we might be setting up an ancestry loop by ignoring the placeholder valuenode here
		// can we check for loops in badly formatted .sifz files somehow?
		if (getenv("SYNFIG_DEBUG_PLACEHOLDER_VALUENODE"))
			printf("%s:%d found a placeholder - skipping loop check\n", __FILE__, __LINE__);
		return ret;
	}

	error("%s:%d BUG: bad type in valuenode '%s'", __FILE__, __LINE__, value_node->get_string().c_str());
	assert(0);
	return ret;
}