Blame synfig-core/src/synfig/valuenodes/valuenode_bone.cpp

Nikita Kitaev dc5e35
/* === S Y N F I G ========================================================= */
Nikita Kitaev dc5e35
/*!	\file valuenode_bone.cpp
Nikita Kitaev dc5e35
**	\brief Implementation of the "Bone" valuenode conversion.
Nikita Kitaev dc5e35
**
Nikita Kitaev dc5e35
**	$Id$
Nikita Kitaev dc5e35
**
Nikita Kitaev dc5e35
**	\legal
Nikita Kitaev dc5e35
**	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
Nikita Kitaev dc5e35
**	Copyright (c) 2007, 2008 Chris Moore
Nikita Kitaev dc5e35
**
Nikita Kitaev dc5e35
**	This package is free software; you can redistribute it and/or
Nikita Kitaev dc5e35
**	modify it under the terms of the GNU General Public License as
Nikita Kitaev dc5e35
**	published by the Free Software Foundation; either version 2 of
Nikita Kitaev dc5e35
**	the License, or (at your option) any later version.
Nikita Kitaev dc5e35
**
Nikita Kitaev dc5e35
**	This package is distributed in the hope that it will be useful,
Nikita Kitaev dc5e35
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
Nikita Kitaev dc5e35
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Nikita Kitaev dc5e35
**	General Public License for more details.
Nikita Kitaev dc5e35
**	\endlegal
Nikita Kitaev dc5e35
*/
Nikita Kitaev dc5e35
/* ========================================================================= */
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
/* === H E A D E R S ======================================================= */
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
#ifdef USING_PCH
Nikita Kitaev dc5e35
#	include "pch.h"
Nikita Kitaev dc5e35
#else
Nikita Kitaev dc5e35
#ifdef HAVE_CONFIG_H
Nikita Kitaev dc5e35
#	include <config.h></config.h>
Nikita Kitaev dc5e35
#endif
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
#include "valuenode_bone.h"
Nikita Kitaev dc5e35
#include "valuenode_const.h"
Nikita Kitaev dc5e35
#include "valuenode_animated.h"
Diego Barrios Romero 07d34c
#include <synfig general.h=""></synfig>
bw 94d8a6
#include <synfig localization.h=""></synfig>
caryoscelus 5eb54b
#include <synfig valuenode_registry.h=""></synfig>
Diego Barrios Romero 07d34c
#include <synfig canvas.h=""></synfig>
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
#endif
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
/* === U S I N G =========================================================== */
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
using namespace std;
Nikita Kitaev dc5e35
using namespace etl;
Nikita Kitaev dc5e35
using namespace synfig;
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
/* === M A C R O S ========================================================= */
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
// #define HIDE_BONE_FIELDS
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
#define GET_NODE_PARENT_NODE(node,t) (*node->get_link("parent"))(t).get(ValueNode_Bone::Handle())
Nikita Kitaev dc5e35
#define GET_NODE_PARENT(node,t) GET_NODE_PARENT_NODE(node,t)->get_guid()
Nikita Kitaev dc5e35
#define GET_NODE_NAME(node,t) node->get_bone_name(t)
Nikita Kitaev dc5e35
#define GET_NODE_BONE(node,t) (*node)(t).get(Bone())
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
#define GET_GUID_CSTR(guid) guid.get_string().substr(0,GUID_PREFIX_LEN).c_str()
Nikita Kitaev dc5e35
#define GET_NODE_GUID_CSTR(node) GET_GUID_CSTR(node->get_guid())
Nikita Kitaev dc5e35
#define GET_NODE_NAME_CSTR(node,t) GET_NODE_NAME(node,t).c_str()
Nikita Kitaev dc5e35
#define GET_NODE_BONE_CSTR(node,t) GET_NODE_BONE(node,t).c_str()
Nikita Kitaev dc5e35
#define GET_NODE_DESC_CSTR(node,t) (node ? strprintf("%s (%s)", GET_NODE_GUID_CSTR(node), GET_NODE_NAME_CSTR(node,t)) : strprintf("%s <root>", GET_GUID_CSTR(GUID(0)))).c_str()</root>
Nikita Kitaev dc5e35
#define GET_NODE_PARENT_CSTR(node,t) GET_GUID_CSTR(GET_NODE_PARENT(node,t))
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
/* === G L O B A L S ======================================================= */
Nikita Kitaev dc5e35
caryoscelus 5eb54b
REGISTER_VALUENODE(ValueNode_Bone, RELEASE_VERSION_0_62_00, "bone", "Bone")
caryoscelus 5eb54b
REGISTER_VALUENODE(ValueNode_Bone_Root, RELEASE_VERSION_0_62_00, "bone_root", "Root Bone")
caryoscelus 5eb54b
Nikita Kitaev dc5e35
static ValueNode_Bone::CanvasMap canvas_map;
Nikita Kitaev dc5e35
static int bone_counter;
Nikita Kitaev dc5e35
// static map<valuenode_bone::handle, matrix=""> animated_matrix_map;</valuenode_bone::handle,>
Nikita Kitaev dc5e35
static Time last_time = Time::begin();
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
static ValueNode_Bone_Root::Handle rooot;
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
/* === P R O C E D U R E S ================================================= */
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
struct compare_bones
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	bool operator() (const ValueNode_Bone::LooseHandle b1, const ValueNode_Bone::LooseHandle b2) const
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		String n1(GET_NODE_NAME(b1,0));
Nikita Kitaev dc5e35
		String n2(GET_NODE_NAME(b2,0));
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		if (n1 < n2) return true;
Nikita Kitaev dc5e35
		if (n1 > n2) return false;
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		return b1->get_guid() < b2->get_guid();
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
};
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
void
Nikita Kitaev dc5e35
ValueNode_Bone::show_bone_map(Canvas::LooseHandle canvas, const char *file, int line, String text, Time t)
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (!getenv("SYNFIG_DEBUG_BONE_MAP")) return;
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	BoneMap bone_map(canvas_map[canvas]);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	set<valuenode_bone::loosehandle, compare_bones=""> bone_set;</valuenode_bone::loosehandle,>
Nikita Kitaev dc5e35
	for (ValueNode_Bone::BoneMap::iterator iter = bone_map.begin(); iter != bone_map.end(); iter++)
Nikita Kitaev dc5e35
		bone_set.insert(iter->second);
Nikita Kitaev dc5e35
Carlos López 9608fb
	printf("\n  %s:%d (canvas %lx) %s we now have %d bones (%d unreachable):\n", file, line, uintptr_t(canvas.get()), text.c_str(), int(bone_map.size()), int(bone_map.size() - bone_set.size()));
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	for (set<valuenode_bone::loosehandle>::iterator iter = bone_set.begin(); iter != bone_set.end(); iter++)</valuenode_bone::loosehandle>
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		ValueNode_Bone::LooseHandle bone(*iter);
Nikita Kitaev dc5e35
		GUID guid(bone->get_guid());
Nikita Kitaev dc5e35
//		printf("%s:%d loop 1 get_node_parent_node\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
		ValueNode_Bone::LooseHandle parent(GET_NODE_PARENT_NODE(bone,t));
Nikita Kitaev dc5e35
		String id;
Nikita Kitaev dc5e35
		if (bone->is_exported()) id = String(" ") + bone->get_id();
Nikita Kitaev dc5e35
//		printf("%s : %s (%d)\n",           		GET_GUID_CSTR(guid), GET_NODE_BONE_CSTR(bone,t), bone->rcount());
Nikita Kitaev dc5e35
		printf("    %-20s : parent %-20s (%d refs, %d rrefs)%s\n",
Nikita Kitaev dc5e35
			   GET_NODE_DESC_CSTR(bone,t),
Nikita Kitaev dc5e35
			   GET_NODE_DESC_CSTR(parent,t),
Nikita Kitaev dc5e35
			   bone->count(), bone->rcount(),
Nikita Kitaev dc5e35
			   id.c_str());
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
	printf("\n");
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
ValueNode_Bone::BoneMap
Nikita Kitaev dc5e35
ValueNode_Bone::get_bone_map(Canvas::ConstHandle canvas)
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	return canvas_map[canvas];
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
ValueNode_Bone::BoneList
Nikita Kitaev dc5e35
ValueNode_Bone::get_ordered_bones(etl::handle<const canvas=""> canvas)</const>
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	std::multimap<valuenode_bone::handle, valuenode_bone::handle=""> uses;</valuenode_bone::handle,>
Nikita Kitaev dc5e35
	std::multimap<valuenode_bone::handle, valuenode_bone::handle=""> is_used_by;</valuenode_bone::handle,>
Nikita Kitaev dc5e35
	BoneList current_list;
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		BoneMap bone_map(canvas_map[canvas]);
Nikita Kitaev dc5e35
		for(BoneMap::const_iterator iter=bone_map.begin();iter!=bone_map.end();++iter)
Nikita Kitaev dc5e35
		{
Nikita Kitaev dc5e35
			ValueNode_Bone::Handle user(iter->second);
Nikita Kitaev dc5e35
			BoneSet ref(get_bones_referenced_by(user, false));
Nikita Kitaev dc5e35
			if (ref.empty())
Nikita Kitaev dc5e35
			{
Nikita Kitaev dc5e35
				if (getenv("SYNFIG_DEBUG_ORDER_BONES_FOR_SAVE_CANVAS")) printf("%s:%d %s doesn't need anybody\n", __FILE__, __LINE__,
Nikita Kitaev dc5e35
					   user->get_bone_name(0).c_str());
Nikita Kitaev dc5e35
				current_list.push_back(user);
Nikita Kitaev dc5e35
			}
Nikita Kitaev dc5e35
			else
Nikita Kitaev dc5e35
				for(BoneSet::iterator iter=ref.begin();iter!=ref.end();++iter)
Nikita Kitaev dc5e35
				{
Nikita Kitaev dc5e35
					ValueNode_Bone::Handle used(*iter);
Nikita Kitaev dc5e35
					if (getenv("SYNFIG_DEBUG_ORDER_BONES_FOR_SAVE_CANVAS")) printf("%s:%d %s is used by %s\n", __FILE__, __LINE__,
Nikita Kitaev dc5e35
																				   used->get_bone_name(0).c_str(),
Nikita Kitaev dc5e35
																				   user->get_bone_name(0).c_str());
Nikita Kitaev dc5e35
					is_used_by.insert(make_pair(used, user));
Nikita Kitaev dc5e35
					uses.insert(make_pair(user, used));
Nikita Kitaev dc5e35
				}
Nikita Kitaev dc5e35
		}
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	BoneList ret;
Nikita Kitaev dc5e35
	BoneSet seen;
Nikita Kitaev dc5e35
	BoneList new_list;
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	while (current_list.size())
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		if (getenv("SYNFIG_DEBUG_ORDER_BONES_FOR_SAVE_CANVAS")) printf("%s:%d current_list has %zd members; we have %zd in is_used_by and %zd in uses\n",
Nikita Kitaev dc5e35
																	   __FILE__, __LINE__, current_list.size(), is_used_by.size(), uses.size());
Nikita Kitaev dc5e35
		for(BoneList::iterator iter=current_list.begin();iter!=current_list.end();++iter)
Nikita Kitaev dc5e35
		{
Nikita Kitaev dc5e35
			ValueNode_Bone::Handle bone(*iter);
Nikita Kitaev dc5e35
			if (getenv("SYNFIG_DEBUG_ORDER_BONES_FOR_SAVE_CANVAS")) printf("%s:%d bone: %s\n", __FILE__, __LINE__, bone->get_bone_name(0).c_str());
Nikita Kitaev dc5e35
			ret.push_back(bone);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
			std::multimap<valuenode_bone::handle, valuenode_bone::handle="">::iterator begin(is_used_by.lower_bound(bone));</valuenode_bone::handle,>
Nikita Kitaev dc5e35
			std::multimap<valuenode_bone::handle, valuenode_bone::handle="">::iterator end(is_used_by.upper_bound(bone));</valuenode_bone::handle,>
Nikita Kitaev dc5e35
			for (std::multimap<valuenode_bone::handle, valuenode_bone::handle="">::iterator iter = begin; iter != end; iter++)</valuenode_bone::handle,>
Nikita Kitaev dc5e35
			{
Nikita Kitaev dc5e35
				ValueNode_Bone::Handle user(iter->second);
Nikita Kitaev dc5e35
				if (getenv("SYNFIG_DEBUG_ORDER_BONES_FOR_SAVE_CANVAS")) printf("\t\t\t%s:%d user: %s\n", __FILE__, __LINE__, user->get_bone_name(0).c_str());
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
				// erase (user,bone) from uses
Nikita Kitaev dc5e35
				if (getenv("SYNFIG_DEBUG_ORDER_BONES_FOR_SAVE_CANVAS")) printf("%s:%d trying to erase - searching %zd\n", __FILE__, __LINE__, uses.count(user));
Nikita Kitaev dc5e35
				std::multimap<valuenode_bone::handle, valuenode_bone::handle="">::iterator begin2(uses.lower_bound(user));</valuenode_bone::handle,>
Nikita Kitaev dc5e35
				std::multimap<valuenode_bone::handle, valuenode_bone::handle="">::iterator end2(uses.upper_bound(user));</valuenode_bone::handle,>
Nikita Kitaev dc5e35
				std::multimap<valuenode_bone::handle, valuenode_bone::handle="">::iterator iter2;</valuenode_bone::handle,>
Nikita Kitaev dc5e35
				for (iter2 = begin2; iter2 != end2; iter2++)
Nikita Kitaev dc5e35
				{
Nikita Kitaev dc5e35
					if (iter2->second == bone)
Nikita Kitaev dc5e35
					{
Nikita Kitaev dc5e35
						uses.erase(iter2);
Nikita Kitaev dc5e35
						if (getenv("SYNFIG_DEBUG_ORDER_BONES_FOR_SAVE_CANVAS")) printf("%s:%d found it\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
						break;
Nikita Kitaev dc5e35
					}
Nikita Kitaev dc5e35
					else
Nikita Kitaev dc5e35
					{
Nikita Kitaev dc5e35
						if (getenv("SYNFIG_DEBUG_ORDER_BONES_FOR_SAVE_CANVAS")) printf("no\n");
Nikita Kitaev dc5e35
					}
Nikita Kitaev dc5e35
				}
Nikita Kitaev dc5e35
				if (iter2 == end2)
Nikita Kitaev dc5e35
				{
Nikita Kitaev dc5e35
					if (getenv("SYNFIG_DEBUG_ORDER_BONES_FOR_SAVE_CANVAS")) printf("%s:%d didn't find it?!?\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
					assert(0);
Nikita Kitaev dc5e35
				}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
				if (getenv("SYNFIG_DEBUG_ORDER_BONES_FOR_SAVE_CANVAS")) printf("%s:%d now there are %zd\n", __FILE__, __LINE__, uses.count(user));
Nikita Kitaev dc5e35
				if (uses.count(user) == 0)
Nikita Kitaev dc5e35
				{
Nikita Kitaev dc5e35
					if (getenv("SYNFIG_DEBUG_ORDER_BONES_FOR_SAVE_CANVAS")) printf("\t\t\t%s:%d adding %s\n", __FILE__, __LINE__, user->get_bone_name(0).c_str());
Nikita Kitaev dc5e35
					new_list.push_back(user);
Nikita Kitaev dc5e35
				}
Nikita Kitaev dc5e35
			}
Nikita Kitaev dc5e35
		}
Nikita Kitaev dc5e35
		current_list = new_list;
Nikita Kitaev dc5e35
		new_list.clear();
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	assert(uses.empty());
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	return ret;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
/* === M E T H O D S ======================================================= */
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
// this should only be used when creating the root bone
Nikita Kitaev dc5e35
ValueNode_Bone::ValueNode_Bone():
d89783
	LinkableValueNode(type_bone_object)
Nikita Kitaev dc5e35
{
Carlos Lopez 0c2d02
	Vocab ret(get_children_vocab());
Carlos Lopez 0c2d02
	set_children_vocab(ret);
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_ROOT_BONE"))
Nikita Kitaev dc5e35
		printf("%s:%d ValueNode_Bone::ValueNode_Bone() this line should only appear once guid %s\n", __FILE__, __LINE__, get_guid().get_string().c_str());
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
ValueNode_Bone::ValueNode_Bone(const ValueBase &value, etl::loose_handle<canvas> canvas):</canvas>
7e2370
	LinkableValueNode(value.get_type())
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_BONE_CONSTRUCTORS"))
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		printf("\n%s:%d ------------------------------------------------------------------------\n", __FILE__, __LINE__);
Carlos López 9608fb
		printf("%s:%d --- ValueNode_Bone() for %s at %lx---\n", __FILE__, __LINE__, GET_GUID_CSTR(get_guid()), uintptr_t(this));
Nikita Kitaev dc5e35
		printf("%s:%d ------------------------------------------------------------------------\n\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
	}
Carlos Lopez 0c2d02
	Vocab ret(get_children_vocab());
Carlos Lopez 0c2d02
	set_children_vocab(ret);
d89783
	Type &type = value.get_type();
d89783
	if (type == type_bone_object)
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		Bone bone(value.get(Bone()));
Nikita Kitaev dc5e35
		String name(bone.get_name());
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		if (name.empty())
Nikita Kitaev dc5e35
			name = strprintf(_("Bone %d"), ++bone_counter);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		name = unique_name(name);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		set_link("name",ValueNode_Const::create(name));
Nikita Kitaev dc5e35
#ifndef HIDE_BONE_FIELDS
Nikita Kitaev dc5e35
		set_link("origin",ValueNode_Const::create(bone.get_origin()));
Nikita Kitaev dc5e35
		set_link("angle",ValueNode_Const::create(bone.get_angle()));
Nikita Kitaev dc5e35
		set_link("scalelx",ValueNode_Const::create(bone.get_scalelx()));
Nikita Kitaev dc5e35
		set_link("scalex",ValueNode_Const::create(bone.get_scalex()));
Nikita Kitaev dc5e35
		set_link("length",ValueNode_Const::create(bone.get_length()));
72429d
		set_link("width",ValueNode_Const::create(bone.get_width()));
72429d
		set_link("tipwidth",ValueNode_Const::create(bone.get_tipwidth()));
[d.j.a.y] Jerome Blanchi 204d73
		set_link("bone_depth",ValueNode_Const::create(bone.get_depth()));
Nikita Kitaev dc5e35
#endif
Nikita Kitaev dc5e35
		ValueNode_Bone::ConstHandle parent(ValueNode_Bone::Handle::cast_const(bone.get_parent()));
Nikita Kitaev dc5e35
		if (!parent) parent = get_root_bone();
Nikita Kitaev dc5e35
		set_link("parent",ValueNode_Const::create(ValueNode_Bone::Handle::cast_const(parent)));
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		if (getenv("SYNFIG_DEBUG_BONE_MAP"))
Nikita Kitaev dc5e35
			printf("%s:%d adding to canvas_map\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
		canvas_map[get_root_canvas()][get_guid()] = this;
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		if (getenv("SYNFIG_DEBUG_SET_PARENT_CANVAS"))
Carlos López 9608fb
			printf("%s:%d set parent canvas for bone %lx to %lx\n", __FILE__, __LINE__, uintptr_t(this), uintptr_t(canvas.get()));
Nikita Kitaev dc5e35
		set_parent_canvas(canvas);
Nikita Kitaev dc5e35
Carlos López 9608fb
		show_bone_map(get_root_canvas(), __FILE__, __LINE__, strprintf("in constructor of %s at %lx", GET_GUID_CSTR(get_guid()), uintptr_t(this)));
Nikita Kitaev dc5e35
	}
d89783
	else
d89783
	{
d89783
		throw Exception::BadType(value.get_type().description.local_name);
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
void ValueNode_Bone::on_changed()
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_ON_CHANGED"))
Nikita Kitaev dc5e35
		printf("%s:%d ValueNode_Bone::on_changed()\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	LinkableValueNode::on_changed();
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
LinkableValueNode*
Nikita Kitaev dc5e35
ValueNode_Bone::create_new()const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	return new ValueNode_Bone(get_type());
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
ValueNode_Bone*
Nikita Kitaev dc5e35
ValueNode_Bone::create(const ValueBase &x, Canvas::LooseHandle canvas)
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	return new ValueNode_Bone(x, canvas);
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
ValueNode_Bone::~ValueNode_Bone()
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_BONE_CONSTRUCTORS"))
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		printf("\n%s:%d ------------------------------------------------------------------------\n", __FILE__, __LINE__);
Carlos López 9608fb
		printf("%s:%d --- ~ValueNode_Bone() for %s at %lx---\n", __FILE__, __LINE__, GET_GUID_CSTR(get_guid()), uintptr_t(this));
Nikita Kitaev dc5e35
		printf("%s:%d ------------------------------------------------------------------------\n\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_BONE_MAP"))
Nikita Kitaev dc5e35
		printf("%s:%d removing from canvas_map\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
	canvas_map[get_root_canvas()].erase(get_guid());
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	show_bone_map(get_root_canvas(), __FILE__, __LINE__, "in destructor");
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	unlink_all();
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
void
Nikita Kitaev dc5e35
ValueNode_Bone::set_guid(const GUID& new_guid)
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	GUID old_guid(get_guid());
Nikita Kitaev dc5e35
	Canvas::LooseHandle canvas(get_root_canvas());
Nikita Kitaev dc5e35
	show_bone_map(canvas, __FILE__, __LINE__, strprintf("before changing guid from %s to %s", GET_GUID_CSTR(old_guid), GET_GUID_CSTR(new_guid)));
Nikita Kitaev dc5e35
	LinkableValueNode::set_guid(new_guid);
Nikita Kitaev dc5e35
	canvas_map[canvas][new_guid] = canvas_map[canvas][old_guid];
Nikita Kitaev dc5e35
	canvas_map[canvas].erase(old_guid);
Nikita Kitaev dc5e35
	show_bone_map(canvas, __FILE__, __LINE__, strprintf("after changing guid from %s to %s", GET_GUID_CSTR(old_guid), GET_GUID_CSTR(new_guid)));
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
void
Nikita Kitaev dc5e35
ValueNode_Bone::set_root_canvas(etl::loose_handle<canvas> canvas)</canvas>
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	GUID guid(get_guid());
Nikita Kitaev dc5e35
	Canvas::LooseHandle old_canvas(get_root_canvas());
Carlos López 9608fb
	show_bone_map(old_canvas, __FILE__, __LINE__, strprintf("before changing canvas from %lx to (%lx)", uintptr_t(old_canvas.get()), uintptr_t(canvas.get())));
Nikita Kitaev dc5e35
	LinkableValueNode::set_root_canvas(canvas);
Nikita Kitaev dc5e35
	Canvas::LooseHandle new_canvas(get_root_canvas()); // it isn't necessarily what we passed in, because set_root_canvas walks up to the root
Nikita Kitaev dc5e35
	if (new_canvas != old_canvas)
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		if (!canvas_map[old_canvas].count(guid))
Carlos López 9608fb
			warning("%s:%d the node we're moving (%lx) isn't in the map", __FILE__, __LINE__, uintptr_t(this));
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		canvas_map[new_canvas][guid] = canvas_map[old_canvas][guid];
Nikita Kitaev dc5e35
		canvas_map[old_canvas].erase(guid);
Carlos López 9608fb
		show_bone_map(new_canvas, __FILE__, __LINE__, strprintf("after changing canvas from %lx to %lx", uintptr_t(old_canvas.get()), uintptr_t(new_canvas.get())));
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
	else
Nikita Kitaev dc5e35
		if (getenv("SYNFIG_DEBUG_BONE_MAP"))
Nikita Kitaev dc5e35
			printf("%s:%d canvases are the same\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
//!Animated Transformation matrix.
Nikita Kitaev dc5e35
//!This matrix applied to a setup point in local
Nikita Kitaev dc5e35
//!coordinates (the one obtained form the Setup
Nikita Kitaev dc5e35
//!Transformation matrix) would obtain the
Nikita Kitaev dc5e35
//!animated position of the point due the current
Nikita Kitaev dc5e35
//!bone influence
Nikita Kitaev dc5e35
Matrix
Nikita Kitaev dc5e35
ValueNode_Bone::get_animated_matrix(Time t, Point child_origin)const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	Real   scalelx	((*scalelx_	)(t).get(Real ()));
Nikita Kitaev dc5e35
	Real   scalex	((*scalex_	)(t).get(Real ()));
Nikita Kitaev dc5e35
	Angle  angle	((*angle_	)(t).get(Angle()));
Nikita Kitaev dc5e35
	Point  origin	((*origin_	)(t).get(Point()));
Nikita Kitaev dc5e35
093a8b
	return get_parent(t)->get_animated_matrix(t, origin)
093a8b
		 * Matrix().set_rotate(angle)
093a8b
		 * Matrix().set_scale(scalex,1.0)
093a8b
		 * Matrix().set_translate(child_origin[0]*scalelx, child_origin[1]);
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
Matrix
Nikita Kitaev dc5e35
ValueNode_Bone::get_animated_matrix(Time t, Real scalex, Real scaley, Angle angle, Point origin, ValueNode_Bone::ConstHandle parent)const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	Matrix parent_matrix(parent->get_animated_matrix(t, origin));
093a8b
	Matrix ret = parent_matrix
093a8b
			   * Matrix().set_rotate(angle)
093a8b
			   * Matrix().set_scale(scalex,scaley);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_ANIMATED_MATRIX_CALCULATION"))
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		printf("%s  *\n", Matrix().set_scale(scalex, scaley).get_string(18, "animated_matrix = ",
Nikita Kitaev dc5e35
																		strprintf("scale(%7.2f, %7.2f) (%s)", scalex, scaley,
Nikita Kitaev dc5e35
																				  get_bone_name(t).c_str())).c_str());
Nikita Kitaev dc5e35
		printf("%s  *\n", Matrix().set_rotate(angle).get_string(18, "", strprintf("rotate(%.2f)", Angle::deg(angle).get())).c_str());
Nikita Kitaev dc5e35
		printf("%s  =\n", parent_matrix.get_string(18, "", "parent").c_str());
Nikita Kitaev dc5e35
		printf("%s\n",	  ret.get_string(18).c_str());
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	return ret;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
ValueNode_Bone::ConstHandle
Nikita Kitaev dc5e35
ValueNode_Bone::get_parent(Time t)const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	// check if we are an ancestor of the proposed parent
Nikita Kitaev dc5e35
	ValueNode_Bone::ConstHandle parent((*parent_)(t).get(ValueNode_Bone::Handle()));
Nikita Kitaev dc5e35
	if (ValueNode_Bone::ConstHandle result = is_ancestor_of(parent,t))
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		if (result == ValueNode_Bone::ConstHandle(this))
Nikita Kitaev dc5e35
			synfig::error("A bone cannot be parent of itself or any of its descendants");
Nikita Kitaev dc5e35
		else
Nikita Kitaev dc5e35
			synfig::error("A loop was detected in the ancestry at bone %s", GET_NODE_DESC_CSTR(result,t));
Nikita Kitaev dc5e35
		printf("%s:%d root 1\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
		return get_root_bone();
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	// proposed parent is root or not a descendant of current bone
Nikita Kitaev dc5e35
	if (parent)
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		return parent;
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
	assert(0);
Nikita Kitaev dc5e35
	return ValueNode_Bone::ConstHandle::cast_dynamic(new ValueNode_Bone_Root);
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
ValueBase
Nikita Kitaev dc5e35
ValueNode_Bone::operator()(Time t)const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_VALUENODE_OPERATORS"))
Nikita Kitaev dc5e35
		printf("%s:%d operator()\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
//	show_bone_map(get_root_canvas(), __FILE__, __LINE__, strprintf("in op() at %s", t.get_string().c_str()), t);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	String bone_name			((*name_	)(t).get(String()));
Nikita Kitaev dc5e35
	ValueNode_Bone::ConstHandle   bone_parent			(get_parent(t));
Nikita Kitaev dc5e35
#ifndef HIDE_BONE_FIELDS
Nikita Kitaev dc5e35
	Point  bone_origin			((*origin_	)(t).get(Point()));
Nikita Kitaev dc5e35
	Angle  bone_angle			((*angle_	)(t).get(Angle()));
Nikita Kitaev dc5e35
	Real   bone_scalelx			((*scalelx_	)(t).get(Real()));
Nikita Kitaev dc5e35
	Real   bone_scalex			((*scalex_	)(t).get(Real()));
Nikita Kitaev dc5e35
	Real   bone_length			((*length_	)(t).get(Real()));
72429d
	Real   bone_width			((*width_	)(t).get(Real()));
4d1c4a
	Real   bone_tipwidth		((*tipwidth_)(t).get(Real()));
[d.j.a.y] Jerome Blanchi 204d73
	Real   bone_depth			((*depth_)(t).get(Real()));
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_ANIMATED_MATRIX_CALCULATION")) printf("\n***\n*** %s:%d get_animated_matrix() for %s\n***\n\n", __FILE__, __LINE__, get_bone_name(t).c_str());
72429d
	Matrix bone_animated_matrix	(get_animated_matrix(t, bone_scalex, 1.0, bone_angle, bone_origin, bone_parent));
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_ANIMATED_MATRIX_CALCULATION")) printf("\n***\n*** %s:%d get_animated_matrix() for %s done\n***\n\n", __FILE__, __LINE__, get_bone_name(t).c_str());
Nikita Kitaev dc5e35
#endif
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	Bone ret;
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	ret.set_name			(bone_name);
Nikita Kitaev dc5e35
	ret.set_parent			(bone_parent.get());
Nikita Kitaev dc5e35
#ifndef HIDE_BONE_FIELDS
Nikita Kitaev dc5e35
	ret.set_origin			(bone_origin);
Nikita Kitaev dc5e35
	ret.set_angle			(bone_angle);
Nikita Kitaev dc5e35
	ret.set_scalelx			(bone_scalelx);
Nikita Kitaev dc5e35
	ret.set_scalex			(bone_scalex);
Nikita Kitaev dc5e35
	ret.set_length			(bone_length);
72429d
	ret.set_width			(bone_width);
72429d
	ret.set_tipwidth		(bone_tipwidth);
[d.j.a.y] Jerome Blanchi 204d73
	ret.set_depth			(bone_depth);
Nikita Kitaev dc5e35
	ret.set_animated_matrix	(bone_animated_matrix);
Nikita Kitaev dc5e35
#endif
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	return ret;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
274049
ValueNode::Handle
Nikita Kitaev dc5e35
ValueNode_Bone::clone(Canvas::LooseHandle canvas, const GUID& deriv_guid)const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	String old_name;
Nikita Kitaev dc5e35
	ValueNode_Const::Handle const_name_link;
Nikita Kitaev dc5e35
	ValueNode::Handle name_link(get_link("name"));
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	if (!name_link->is_exported())
Nikita Kitaev dc5e35
	{
Carlos Lopez ec95a1
		const_name_link = ValueNode_Const::Handle::cast_dynamic(name_link);
Carlos Lopez ec95a1
		if (const_name_link)
Nikita Kitaev dc5e35
		{
Nikita Kitaev dc5e35
			String name(old_name = const_name_link->get_value().get(String()));
Nikita Kitaev dc5e35
//			printf("got old name '%s'\n", name.c_str());
Nikita Kitaev dc5e35
			name = unique_name(name);
Nikita Kitaev dc5e35
//			printf("using new name '%s'\n", name.c_str());
Nikita Kitaev dc5e35
			const_name_link->set_value(name);
Nikita Kitaev dc5e35
		}
Nikita Kitaev dc5e35
//		else
Nikita Kitaev dc5e35
//			printf("%s:%d bone's name is not constant, so not editing\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
//	else
Nikita Kitaev dc5e35
//		printf("%s:%d cloned bone's name is exported, so not editing\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
274049
	ValueNode::Handle ret(LinkableValueNode::clone(canvas, deriv_guid));
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	if (const_name_link)
Nikita Kitaev dc5e35
		const_name_link->set_value(old_name);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	return ret;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
String
Nikita Kitaev dc5e35
ValueNode_Bone::get_bone_name(Time t)const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	return (*get_link("name"))(t).get(String());
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
bool
d89783
ValueNode_Bone::check_type(Type &type)
Nikita Kitaev dc5e35
{
d89783
	return type==type_bone_object;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
bool
Nikita Kitaev dc5e35
ValueNode_Bone::set_link_vfunc(int i,ValueNode::Handle value)
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	assert(i>=0 && i
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	switch(i)
Nikita Kitaev dc5e35
	{
d89783
	case 0: CHECK_TYPE_AND_SET_VALUE(name_, type_string);
Nikita Kitaev dc5e35
	case 1:
Nikita Kitaev dc5e35
	{
d89783
		VALUENODE_CHECK_TYPE(type_bone_valuenode);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		// check for loops
Nikita Kitaev dc5e35
		ValueNode_Bone::BoneSet parents(ValueNode_Bone::get_bones_referenced_by(value));
Nikita Kitaev dc5e35
		if (parents.count(this))
Nikita Kitaev dc5e35
		{
Nikita Kitaev dc5e35
			error("creating potential loops in the bone ancestry isn't allowed");
Nikita Kitaev dc5e35
			return false;
Nikita Kitaev dc5e35
		}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		VALUENODE_SET_VALUE(parent_);
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
#ifndef HIDE_BONE_FIELDS
d89783
	case 2: CHECK_TYPE_AND_SET_VALUE(origin_,	type_vector);
d89783
	case 3: CHECK_TYPE_AND_SET_VALUE(angle_,	type_angle);
d89783
	case 4: CHECK_TYPE_AND_SET_VALUE(scalelx_,	type_real);
72429d
	case 5: CHECK_TYPE_AND_SET_VALUE(width_,	type_real);
d89783
	case 6: CHECK_TYPE_AND_SET_VALUE(scalex_,	type_real);
72429d
	case 7: CHECK_TYPE_AND_SET_VALUE(tipwidth_,	type_real);
[d.j.a.y] Jerome Blanchi 204d73
	case 8: CHECK_TYPE_AND_SET_VALUE(depth_,	type_real);
4d1c4a
	case 9: CHECK_TYPE_AND_SET_VALUE(length_,	type_real);
Nikita Kitaev dc5e35
#endif
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
	return false;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
ValueNode::LooseHandle
Nikita Kitaev dc5e35
ValueNode_Bone::get_link_vfunc(int i)const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	assert(i>=0 && i
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	switch(i)
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
	case 0: return name_;
Nikita Kitaev dc5e35
	case 1: return parent_;
Nikita Kitaev dc5e35
#ifndef HIDE_BONE_FIELDS
Nikita Kitaev dc5e35
	case 2: return origin_;
Nikita Kitaev dc5e35
	case 3: return angle_;
Nikita Kitaev dc5e35
	case 4: return scalelx_;
72429d
	case 5: return width_;
Nikita Kitaev dc5e35
	case 6: return scalex_;
72429d
	case 7: return tipwidth_;
[d.j.a.y] Jerome Blanchi 204d73
	case 8: return depth_;
4d1c4a
	case 9: return length_;
Nikita Kitaev dc5e35
#endif
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	return 0;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Carlos Lopez 0c2d02
LinkableValueNode::Vocab
Carlos Lopez 0c2d02
ValueNode_Bone::get_children_vocab_vfunc() const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
Carlos Lopez 0c2d02
	LinkableValueNode::Vocab ret;
Carlos Lopez 0c2d02
Carlos Lopez 0c2d02
	ret.push_back(ParamDesc(ValueBase(),"name")
Carlos Lopez 0c2d02
		.set_local_name(_("Name"))
Carlos Lopez 0c2d02
		.set_description(_("The name of the bone"))
Carlos Lopez 0c2d02
	);
Carlos Lopez 0c2d02
Carlos Lopez 0c2d02
	ret.push_back(ParamDesc(ValueBase(),"parent")
Carlos Lopez 0c2d02
		.set_local_name(_("Parent"))
Carlos Lopez 0c2d02
		.set_description(_("The parent bone of the bone"))
Carlos Lopez 0c2d02
	);
Carlos Lopez 0c2d02
4d1c4a
	ret.push_back(ParamDesc(ValueBase(),"origin")
Carlos Lopez 0c2d02
		.set_local_name(_("Origin"))
Carlos Lopez 0c2d02
		.set_description(_("The rotating origin of the bone relative to its parent"))
Carlos Lopez 0c2d02
	);
Carlos Lopez 0c2d02
4d1c4a
	ret.push_back(ParamDesc(ValueBase(),"angle")
Carlos Lopez 0c2d02
		.set_local_name(_("Angle"))
Carlos Lopez 0c2d02
		.set_description(_("The rotating angle of the bone relative to its parent"))
Carlos Lopez 0c2d02
	);
Carlos Lopez 0c2d02
4d1c4a
	ret.push_back(ParamDesc(ValueBase(),"scalelx")
Carlos Lopez 0c2d02
		.set_local_name(_("Local Length Scale"))
Firas Hanife b4b6a7
		.set_description(_("The scale of the bone aligned to its length"))
Carlos Lopez 0c2d02
	);
Carlos Lopez 0c2d02
4d1c4a
	ret.push_back(ParamDesc(ValueBase(),"width")
72429d
		.set_local_name(_("Bone Width"))
72429d
		.set_description(_("Bone width at its origin"))
Carlos Lopez 0c2d02
	);
Carlos Lopez 0c2d02
4d1c4a
	ret.push_back(ParamDesc(ValueBase(),"scalex")
Carlos Lopez 0c2d02
		.set_local_name(_("Recursive Length Scale"))
Carlos Lopez 0c2d02
		.set_description(_("The scale of the bone and its children aligned to its length"))
Carlos Lopez 0c2d02
	);
Carlos Lopez 0c2d02
4d1c4a
	ret.push_back(ParamDesc(ValueBase(),"tipwidth")
72429d
		.set_local_name(_("Tip Width"))
72429d
		.set_description(_("Bone width at its tip"))
Carlos Lopez 0c2d02
	);
Carlos Lopez 0c2d02
[d.j.a.y] Jerome Blanchi 204d73
	ret.push_back(ParamDesc(ValueBase(),"bone_depth")
[d.j.a.y] Jerome Blanchi 204d73
		.set_local_name(_("Z-Depth"))
[d.j.a.y] Jerome Blanchi 204d73
		.set_description(_("The z-depth of the bone"))
4d1c4a
	);
4d1c4a
4d1c4a
	ret.push_back(ParamDesc(ValueBase(),"length")
Carlos Lopez 0c2d02
		.set_local_name(_("Length Setup"))
Carlos Lopez 0c2d02
		.set_description(_("The length of the bone at setup"))
Carlos Lopez 0c2d02
	);
Carlos Lopez 0c2d02
Carlos Lopez 0c2d02
	return ret;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
ValueNode_Bone::LooseHandle
Nikita Kitaev dc5e35
ValueNode_Bone::find(String name)const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	// printf("%s:%d finding '%s' : ", __FILE__, __LINE__, name.c_str());
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	BoneMap bone_map(canvas_map[get_root_canvas()]);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	for (ValueNode_Bone::BoneMap::iterator iter =  bone_map.begin(); iter != bone_map.end(); iter++)
Nikita Kitaev dc5e35
		if ((*iter->second->get_link("name"))(0).get(String()) == name)
Nikita Kitaev dc5e35
		{
Nikita Kitaev dc5e35
			// printf("yes\n");
Nikita Kitaev dc5e35
			return iter->second;
Nikita Kitaev dc5e35
		}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	// printf("no\n");
Nikita Kitaev dc5e35
	return 0;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
String
Nikita Kitaev dc5e35
ValueNode_Bone::unique_name(String name)const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (!find(name))
Nikita Kitaev dc5e35
		return name;
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	// printf("%s:%d making unique name for '%s'\n", __FILE__, __LINE__, name.c_str());
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	size_t last_close(name.size()-1);
Nikita Kitaev dc5e35
	int number = -1;
Nikita Kitaev dc5e35
	String prefix;
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	do
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		if (name.substr(last_close) != ")")
Nikita Kitaev dc5e35
			break;
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		size_t last_open(name.rfind('('));
Nikita Kitaev dc5e35
		if (last_open == String::npos)
Nikita Kitaev dc5e35
			break;
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		if (last_open+2 > last_close)
Nikita Kitaev dc5e35
			break;
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		String between(name.substr(last_open+1, last_close - (last_open+1)));
Nikita Kitaev dc5e35
		String::iterator iter;
Nikita Kitaev dc5e35
		for (iter = between.begin(); iter != between.end(); iter++)
Nikita Kitaev dc5e35
			if (!isdigit(*iter))
Nikita Kitaev dc5e35
				break;
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		if (iter != between.end())
Nikita Kitaev dc5e35
			break;
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		prefix = name.substr(0, last_open);
Nikita Kitaev dc5e35
		number = atoi(between.c_str());
Nikita Kitaev dc5e35
	} while (0);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	if (number == -1)
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		prefix = name + " ";
Nikita Kitaev dc5e35
		number = 2;
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	do
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		name = prefix + "(" + strprintf("%d", number++) + ")";
Nikita Kitaev dc5e35
	} while (find(name));
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	// printf("%s:%d unique name is '%s'\n", __FILE__, __LINE__, name.c_str());
Nikita Kitaev dc5e35
	return name;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
// checks whether the current object is an ancestor of the supplied bone
Nikita Kitaev dc5e35
// returns a handle to NULL if it isn't
Nikita Kitaev dc5e35
// if there's a loop in the ancestry it returns a handle to the valuenode where the loop is detected
Nikita Kitaev dc5e35
// otherwise it returns the current object
Nikita Kitaev dc5e35
ValueNode_Bone::ConstHandle
Nikita Kitaev dc5e35
ValueNode_Bone::is_ancestor_of(ValueNode_Bone::ConstHandle bone, Time t)const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	ValueNode_Bone::ConstHandle ancestor(this);
Nikita Kitaev dc5e35
	set<valuenode_bone::consthandle> seen;</valuenode_bone::consthandle>
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_ANCESTOR_CHECK"))
Nikita Kitaev dc5e35
		printf("%s:%d checking whether %s is ancestor of %s\n", __FILE__, __LINE__, GET_NODE_DESC_CSTR(ancestor,t), GET_NODE_DESC_CSTR(bone,t));
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	while (bone != get_root_bone())
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		if (bone == ancestor)
Nikita Kitaev dc5e35
		{
Nikita Kitaev dc5e35
			if (getenv("SYNFIG_DEBUG_ANCESTOR_CHECK"))
Nikita Kitaev dc5e35
				printf("%s:%d bone reached us - so we are its ancestor - return true\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
			return bone;
Nikita Kitaev dc5e35
		}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		if (seen.count(bone))
Nikita Kitaev dc5e35
		{
Nikita Kitaev dc5e35
			if (getenv("SYNFIG_DEBUG_ANCESTOR_CHECK"))
Nikita Kitaev dc5e35
				printf("%s:%d stuck in a loop - return true\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
			return bone;
Nikita Kitaev dc5e35
		}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		seen.insert(bone);
Nikita Kitaev dc5e35
		bone=GET_NODE_PARENT_NODE(bone,t);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		if (getenv("SYNFIG_DEBUG_ANCESTOR_CHECK"))
Nikita Kitaev dc5e35
			printf("%s:%d step on to parent %s\n", __FILE__, __LINE__, GET_NODE_DESC_CSTR(bone,t));
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_ANCESTOR_CHECK"))
Nikita Kitaev dc5e35
		printf("%s:%d reached root - return false\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
	return 0;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
ValueNode_Bone::BoneSet
Nikita Kitaev dc5e35
ValueNode_Bone::get_bones_referenced_by(ValueNode::Handle value_node, bool recursive)
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	// printf("%s:%d rec = %d\n", __FILE__, __LINE__,recursive);
Nikita Kitaev dc5e35
	BoneSet ret;
Nikita Kitaev dc5e35
	if (!value_node)
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		printf("%s:%d failed?\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
		assert(0);
Nikita Kitaev dc5e35
		return ret;
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	// if it's a ValueNode_Const
Nikita Kitaev dc5e35
	if (ValueNode_Const::Handle value_node_const = ValueNode_Const::Handle::cast_dynamic(value_node))
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		ValueBase value_node(value_node_const->get_value());
d89783
		if (value_node.get_type() == type_bone_valuenode)
Nikita Kitaev dc5e35
			if (ValueNode_Bone::Handle bone = value_node.get(ValueNode_Bone::Handle()))
Nikita Kitaev dc5e35
			{
Nikita Kitaev dc5e35
				// do we want to check for bone references in other bone fields or just 'parent'?
Nikita Kitaev dc5e35
				if (recursive)
Nikita Kitaev dc5e35
				{
Nikita Kitaev dc5e35
					// printf("%s:%d rec\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
					ret = get_bones_referenced_by(bone, recursive);
Nikita Kitaev dc5e35
					// ret = get_bones_referenced_by(bone->get_link("parent"), recursive);
Nikita Kitaev dc5e35
				}
Nikita Kitaev dc5e35
				if (!bone->is_root())
Nikita Kitaev dc5e35
					ret.insert(bone);
Nikita Kitaev dc5e35
			}
Nikita Kitaev dc5e35
		return ret;
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	// if it's a ValueNode_Animated
Nikita Kitaev dc5e35
	if (ValueNode_Animated::Handle value_node_animated = ValueNode_Animated::Handle::cast_dynamic(value_node))
Nikita Kitaev dc5e35
	{
d89783
		// ValueNode_Animated::Handle ret = ValueNode_Animated::create(type_bone_object);
Nikita Kitaev dc5e35
		ValueNode_Animated::WaypointList list(value_node_animated->waypoint_list());
Nikita Kitaev dc5e35
		for (ValueNode_Animated::WaypointList::iterator iter = list.begin(); iter != list.end(); iter++)
Nikita Kitaev dc5e35
		{
Nikita Kitaev dc5e35
//			printf("%s:%d getting bones from waypoint\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
			BoneSet ret2(get_bones_referenced_by(iter->get_value_node(), recursive));
Nikita Kitaev dc5e35
			ret.insert(ret2.begin(), ret2.end());
Nikita Kitaev dc5e35
//			printf("added %d bones from waypoint to get %d\n", int(ret2.size()), int(ret.size()));
Nikita Kitaev dc5e35
		}
Nikita Kitaev dc5e35
//		printf("returning %d bones\n", int(ret.size()));
Nikita Kitaev dc5e35
		return ret;
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	// if it's a LinkableValueNode
Nikita Kitaev dc5e35
	if (LinkableValueNode::Handle linkable_value_node = LinkableValueNode::Handle::cast_dynamic(value_node))
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		for (int i = 0; i < linkable_value_node->link_count(); i++)
Nikita Kitaev dc5e35
		{
Nikita Kitaev dc5e35
			BoneSet ret2(get_bones_referenced_by(linkable_value_node->get_link(i), recursive));
Nikita Kitaev dc5e35
			ret.insert(ret2.begin(), ret2.end());
Nikita Kitaev dc5e35
		}
Nikita Kitaev dc5e35
		return ret;
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	if (PlaceholderValueNode::Handle linkable_value_node = PlaceholderValueNode::Handle::cast_dynamic(value_node))
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		// todo: while loading we might be setting up an ancestry loop by ignoring the placeholder valuenode here
Nikita Kitaev dc5e35
		// can we check for loops in badly formatted .sifz files somehow?
Nikita Kitaev dc5e35
		if (getenv("SYNFIG_DEBUG_PLACEHOLDER_VALUENODE"))
Nikita Kitaev dc5e35
			printf("%s:%d found a placeholder - skipping loop check\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
		return ret;
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	error("%s:%d BUG: bad type in valuenode '%s'", __FILE__, __LINE__, value_node->get_string().c_str());
Nikita Kitaev dc5e35
	assert(0);
Nikita Kitaev dc5e35
	return ret;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
ValueNode_Bone::BoneSet
Nikita Kitaev dc5e35
ValueNode_Bone::get_bones_affected_by(ValueNode::Handle value_node)
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	BoneSet ret;
Nikita Kitaev dc5e35
	set<const node*=""> seen, current_nodes, new_nodes;</const>
Nikita Kitaev dc5e35
	int generation = 0;
Nikita Kitaev dc5e35
	bool debug(false);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_SUITABLE_PARENTS"))
Nikita Kitaev dc5e35
		debug = true;
Nikita Kitaev dc5e35
Carlos López 9608fb
	if (debug) printf("getting bones affected by %lx %s\n", uintptr_t(value_node.get()), value_node->get_string().c_str());
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	// initialise current_nodes with the node we're editing
Nikita Kitaev dc5e35
	current_nodes.insert(value_node.get());
Nikita Kitaev dc5e35
	do
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		generation++;
Nikita Kitaev dc5e35
		if (debug) printf("generation %d has %zd nodes\n", generation, current_nodes.size());
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		int count = 0;
Nikita Kitaev dc5e35
		// loop through current_nodes
Nikita Kitaev dc5e35
		for (set<const node*="">::iterator iter = current_nodes.begin(); iter != current_nodes.end(); iter++, count++)</const>
Nikita Kitaev dc5e35
		{
Nikita Kitaev dc5e35
			// loop through the parents of each node in current_nodes
Nikita Kitaev dc5e35
			set<node*> node_parents((*iter)->parent_set);</node*>
Nikita Kitaev dc5e35
			if (debug) printf("%s:%d node %d %lx (%s) has %zd parents\n",
Carlos López 9608fb
							  __FILE__, __LINE__, count, uintptr_t(*iter), (*iter)->get_string().c_str(), node_parents.size());
Nikita Kitaev dc5e35
			int count2 = 0;
Nikita Kitaev dc5e35
			for (set<node*>::iterator iter2 = node_parents.begin(); iter2 != node_parents.end(); iter2++, count2++)</node*>
Nikita Kitaev dc5e35
			{
Nikita Kitaev dc5e35
				Node* node(*iter2);
Carlos López 9608fb
				// if (debug) printf("%s:%d parent %d: %lx (%s)\n", __FILE__, __LINE__, count2, uintptr_t(node), node->get_string().c_str());
Nikita Kitaev dc5e35
				// for each parent we've not already seen
Nikita Kitaev dc5e35
				if (!seen.count(node))
Nikita Kitaev dc5e35
				{
Nikita Kitaev dc5e35
					// note that we've seen it now
Nikita Kitaev dc5e35
					seen.insert(node);
Nikita Kitaev dc5e35
					// add it to the list of new nodes to loop though in the next iteration
Nikita Kitaev dc5e35
					new_nodes.insert(node);
Nikita Kitaev dc5e35
					// and if it's a ValueNode_Bone, add it to the set to be returned
Nikita Kitaev dc5e35
					if (dynamic_cast<valuenode_bone*>(node))</valuenode_bone*>
Nikita Kitaev dc5e35
						ret.insert(dynamic_cast<valuenode_bone*>(node));</valuenode_bone*>
Nikita Kitaev dc5e35
				}
Nikita Kitaev dc5e35
			}
Nikita Kitaev dc5e35
		}
Nikita Kitaev dc5e35
		current_nodes = new_nodes;
Nikita Kitaev dc5e35
		new_nodes.clear();
Nikita Kitaev dc5e35
	} while (current_nodes.size());
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	if (debug) printf("%s:%d got %zd affected bones\n", __FILE__, __LINE__, ret.size());
Nikita Kitaev dc5e35
	return ret;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
ValueNode_Bone::BoneSet
Nikita Kitaev dc5e35
ValueNode_Bone::get_possible_parent_bones(ValueNode::Handle value_node)
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	BoneSet ret;
Nikita Kitaev dc5e35
	bool debug(false);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_SUITABLE_PARENTS"))
Nikita Kitaev dc5e35
		debug = true;
Nikita Kitaev dc5e35
Carlos López 9608fb
	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());
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	// which bones are we currently editing the parent of - it can be more than one due to linking
Nikita Kitaev dc5e35
	ValueNode_Bone::BoneSet affected_bones(ValueNode_Bone::get_bones_affected_by(value_node));
Nikita Kitaev dc5e35
	if (debug) printf("%s:%d got %zd affected bones\n", __FILE__, __LINE__, affected_bones.size());
Nikita Kitaev dc5e35
	Canvas::LooseHandle canvas(value_node->get_root_canvas());
Carlos López 9608fb
	if (debug) printf("%s:%d canvas %lx\n", __FILE__, __LINE__, uintptr_t(canvas.get()));
Nikita Kitaev dc5e35
	for (ValueNode_Bone::BoneSet::iterator iter = affected_bones.begin(); iter != affected_bones.end(); iter++)
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		if (!canvas)
Nikita Kitaev dc5e35
		{
Nikita Kitaev dc5e35
			canvas = (*iter)->get_root_canvas();
Carlos López 9608fb
			printf("%s:%d root canvas %lx\n", __FILE__, __LINE__, uintptr_t((*iter)->get_root_canvas().get()));
Carlos López 9608fb
			printf("%s:%d parent canvas %lx\n", __FILE__, __LINE__, uintptr_t((*iter)->get_parent_canvas().get()));
Carlos López 9608fb
			printf("%s:%d ancestor canvas %lx\n", __FILE__, __LINE__, uintptr_t((*iter)->get_non_inline_ancestor_canvas().get()));
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		}
Nikita Kitaev dc5e35
		if (canvas != (*iter)->get_root_canvas())
Nikita Kitaev dc5e35
			warning("%s:%d multiple root canvases in affected bones: %lx and %lx", __FILE__, __LINE__,
Carlos López 9608fb
					uintptr_t(canvas.get()), uintptr_t((*iter)->get_root_canvas().get()));
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	BoneMap bone_map(canvas_map[canvas]);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	// loop through all the bones that exist
Nikita Kitaev dc5e35
	for (ValueNode_Bone::BoneMap::const_iterator iter=bone_map.begin(); iter!=bone_map.end(); iter++)
Nikita Kitaev dc5e35
	{
Nikita Kitaev dc5e35
		ValueNode_Bone::Handle bone_value_node(iter->second);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		// if the bone would be affected by our editing, skip it - it would cause a loop if the user selected it
Nikita Kitaev dc5e35
		if (affected_bones.count(bone_value_node.get()))
Nikita Kitaev dc5e35
			continue;
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
		// loop through the list of bones referenced by this bone's parent link;
Nikita Kitaev dc5e35
		// if any of them would be affected by editing the cell, don't offer this bone in the menu
Nikita Kitaev dc5e35
		{
Nikita Kitaev dc5e35
			ValueNode_Bone::BoneSet parents(ValueNode_Bone::get_bones_referenced_by(bone_value_node->get_link("parent")));
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
			ValueNode_Bone::BoneSet::iterator iter;
Nikita Kitaev dc5e35
			for (iter = parents.begin(); iter != parents.end(); iter++)
Nikita Kitaev dc5e35
				if (affected_bones.count(iter->get()))
Nikita Kitaev dc5e35
					break;
Nikita Kitaev dc5e35
			if (iter == parents.end())
Nikita Kitaev dc5e35
				ret.insert(bone_value_node);
Nikita Kitaev dc5e35
		}
Nikita Kitaev dc5e35
	}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	if (debug) printf("%s:%d returning %zd possible parents\n", __FILE__, __LINE__, ret.size());
Nikita Kitaev dc5e35
	return ret;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
ValueNode_Bone::Handle
Nikita Kitaev dc5e35
ValueNode_Bone::get_root_bone()
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (!rooot) rooot = new ValueNode_Bone_Root();
Nikita Kitaev dc5e35
	return rooot;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
#ifdef _DEBUG
Nikita Kitaev dc5e35
void
Nikita Kitaev dc5e35
ValueNode_Bone::ref()const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_BONE_REFCOUNT"))
Nikita Kitaev dc5e35
		printf("%s:%d %s   ref valuenode_bone %*s -> %2d\n", __FILE__, __LINE__, GET_GUID_CSTR(get_guid()), (count()*2), "", count()+1);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	LinkableValueNode::ref();
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
bool
Nikita Kitaev dc5e35
ValueNode_Bone::unref()const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_BONE_REFCOUNT"))
Nikita Kitaev dc5e35
		printf("%s:%d %s unref valuenode_bone %*s%2d <-\n", __FILE__, __LINE__, GET_GUID_CSTR(get_guid()), ((count()-1)*2), "", count()-1);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	return LinkableValueNode::unref();
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
void
Nikita Kitaev dc5e35
ValueNode_Bone::rref()const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_BONE_REFCOUNT"))
Nikita Kitaev dc5e35
		printf("%s:%d %s               rref valuenode_bone %d -> ", __FILE__, __LINE__, GET_GUID_CSTR(get_guid()), rcount());
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	LinkableValueNode::rref();
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_BONE_REFCOUNT"))
Nikita Kitaev dc5e35
		printf("%d\n", rcount());
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
void
Nikita Kitaev dc5e35
ValueNode_Bone::runref()const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_BONE_REFCOUNT"))
Nikita Kitaev dc5e35
		printf("%s:%d %s             runref valuenode_bone %d -> ", __FILE__, __LINE__, GET_GUID_CSTR(get_guid()), rcount());
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	LinkableValueNode::runref();
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_BONE_REFCOUNT"))
Nikita Kitaev dc5e35
		printf("%d\n", rcount());
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
#endif
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
// ------------------------------------------------------------------------
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
ValueNode_Bone_Root::ValueNode_Bone_Root()
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_ROOT_BONE"))
Nikita Kitaev dc5e35
		printf("%s:%d ValueNode_Bone_Root::ValueNode_Bone_Root()\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
ValueNode_Bone_Root::~ValueNode_Bone_Root()
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_ROOT_BONE"))
Nikita Kitaev dc5e35
		printf("%s:%d ValueNode_Bone_Root::~ValueNode_Bone_Root()\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
ValueBase
Nikita Kitaev dc5e35
ValueNode_Bone_Root::operator()(Time t __attribute__ ((unused)))const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	Bone ret;
Nikita Kitaev dc5e35
	ret.set_name			(get_local_name());
Nikita Kitaev dc5e35
	ret.set_parent			(0);
Nikita Kitaev dc5e35
	return ret;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
void
Nikita Kitaev dc5e35
ValueNode_Bone_Root::set_guid(const GUID& new_guid)
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_ROOT_BONE"))
Nikita Kitaev dc5e35
		printf("%s:%d bypass set_guid() for root bone\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
	LinkableValueNode::set_guid(new_guid);
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
void
Nikita Kitaev dc5e35
ValueNode_Bone_Root::set_root_canvas(etl::loose_handle<canvas> canvas)</canvas>
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_ROOT_BONE"))
Nikita Kitaev dc5e35
		printf("%s:%d bypass set_root_canvas() for root bone\n", __FILE__, __LINE__);
Nikita Kitaev dc5e35
	LinkableValueNode::set_root_canvas(canvas);
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
ValueNode_Bone*
Nikita Kitaev dc5e35
ValueNode_Bone_Root::create(const ValueBase &x __attribute__ ((unused)))
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	return get_root_bone().get();
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
String
Nikita Kitaev dc5e35
ValueNode_Bone_Root::get_bone_name(Time t __attribute__ ((unused)))const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	return get_local_name();
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
int
Nikita Kitaev dc5e35
ValueNode_Bone_Root::link_count()const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	return 0;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
LinkableValueNode*
Nikita Kitaev dc5e35
ValueNode_Bone_Root::create_new()const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	assert(0);
Nikita Kitaev dc5e35
	return rooot.get();
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
Matrix
Nikita Kitaev dc5e35
ValueNode_Bone_Root::get_animated_matrix(Time t __attribute__ ((unused)), Point child_origin)const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	return Matrix().set_translate(child_origin);
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
bool
d89783
ValueNode_Bone_Root::check_type(Type &type __attribute__ ((unused)))
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	return false;
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
#ifdef _DEBUG
Nikita Kitaev dc5e35
void
Nikita Kitaev dc5e35
ValueNode_Bone_Root::ref()const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_BONE_REFCOUNT"))
Nikita Kitaev dc5e35
		printf("%s:%d %s   ref valuenode_bone_root %*s -> %2d\n", __FILE__, __LINE__, GET_GUID_CSTR(get_guid()), (count()*2), "", count()+1);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	LinkableValueNode::ref();
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
bool
Nikita Kitaev dc5e35
ValueNode_Bone_Root::unref()const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_BONE_REFCOUNT"))
Nikita Kitaev dc5e35
		printf("%s:%d %s unref valuenode_bone_root %*s%2d <-\n", __FILE__, __LINE__, GET_GUID_CSTR(get_guid()), ((count()-1)*2), "", count()-1);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	return LinkableValueNode::unref();
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
void
Nikita Kitaev dc5e35
ValueNode_Bone_Root::rref()const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_BONE_REFCOUNT"))
Nikita Kitaev dc5e35
		printf("%s:%d %s               rref valuenode_bone_root %d -> ", __FILE__, __LINE__, GET_GUID_CSTR(get_guid()), rcount());
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	LinkableValueNode::rref();
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_BONE_REFCOUNT"))
Nikita Kitaev dc5e35
		printf("%d\n", rcount());
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
void
Nikita Kitaev dc5e35
ValueNode_Bone_Root::runref()const
Nikita Kitaev dc5e35
{
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_BONE_REFCOUNT"))
Nikita Kitaev dc5e35
		printf("%s:%d %s             runref valuenode_bone_root %d -> ", __FILE__, __LINE__, GET_GUID_CSTR(get_guid()), rcount());
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	LinkableValueNode::runref();
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	if (getenv("SYNFIG_DEBUG_BONE_REFCOUNT"))
Nikita Kitaev dc5e35
		printf("%d\n", rcount());
Nikita Kitaev dc5e35
}
Nikita Kitaev dc5e35
#endif