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; }
ValueNode_Switch::ValueNode_Switch(const ValueNode::Handle &x): LinkableValueNode(x->get_type()) { Vocab ret(get_children_vocab()); set_children_vocab(ret); set_link("link_off",x); set_link("link_on",x); set_link("switch",ValueNode_Const::create(bool(false))); }
ValueNode_TimeLoop::ValueNode_TimeLoop(const ValueNode::Handle &x): LinkableValueNode(x->get_type()) { Vocab ret(get_children_vocab()); set_children_vocab(ret); set_link("link", x); set_link("link_time", ValueNode_Const::create(Time(0))); set_link("local_time", ValueNode_Const::create(Time(0))); set_link("duration", ValueNode_Const::create(Time(1))); }
bool ValueNode_DynamicList::set_link_vfunc(int i,ValueNode::Handle x) { assert(i>=0); if((unsigned)i>=list.size()) return false; if(x->get_type()!=*container_type) return false; list[i].value_node=x; return true; }
bool ValueNode_StaticList::set_link_vfunc(int i,ValueNode::Handle x) // line 628 { assert(i>=0); if((unsigned)i>=list.size()) return false; if(x->get_type()!=*container_type) return false; list[i]=x; return true; }
ValueNode_BoneInfluence::ValueNode_BoneInfluence(const ValueNode::Handle &x, Canvas::LooseHandle canvas): LinkableValueNode(x->get_type()), checked_inverse_(), has_inverse_() { Type &type(x->get_type()); if (type == type_vector || type == type_bline_point) { ValueNode_StaticList::Handle bone_weight_list(ValueNode_StaticList::create(type_bone_weight_pair, canvas)); bone_weight_list->add(ValueNode_BoneWeightPair::create(BoneWeightPair(Bone(), 1), canvas)); set_link("bone_weight_list", bone_weight_list); set_link("link", x); if (getenv("SYNFIG_DEBUG_SET_PARENT_CANVAS")) printf("%s:%d set parent canvas for bone influence to %lx\n", __FILE__, __LINE__, uintptr_t(canvas.get())); set_parent_canvas(canvas); } else { throw Exception::BadType(type.description.local_name); } }
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; }
ValueNode_BoneInfluence::ValueNode_BoneInfluence(const ValueNode::Handle &x, Canvas::LooseHandle canvas): LinkableValueNode(x->get_type()) { switch(x->get_type()) { case ValueBase::TYPE_VECTOR: case ValueBase::TYPE_BLINEPOINT: //case ValueBase::TYPE_BLINE: { ValueNode_StaticList::Handle bone_weight_list(ValueNode_StaticList::create(ValueBase::TYPE_BONE_WEIGHT_PAIR, canvas)); bone_weight_list->add(ValueNode_BoneWeightPair::create(BoneWeightPair(Bone(), 1), canvas)); set_link("bone_weight_list", bone_weight_list); set_link("link", x); if (getenv("SYNFIG_DEBUG_SET_PARENT_CANVAS")) printf("%s:%d set parent canvas for bone influence to %lx\n", __FILE__, __LINE__, uintptr_t(canvas.get())); set_parent_canvas(canvas); break; } default: throw Exception::BadType(ValueBase::type_local_name(x->get_type())); } }
void swap_guid(const ValueNode::Handle& a,const ValueNode::Handle& b) { synfig::GUID old_a(a->get_guid()); a->set_guid(synfig::GUID()); synfig::GUID old_b(b->get_guid()); b->set_guid(synfig::GUID()); a->set_guid(old_b); b->set_guid(old_a); }
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; }
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); }
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; }
bool ValueNode_Composite::set_link_vfunc(int i,ValueNode::Handle x) { assert(i>=0 && i<link_count()); if(PlaceholderValueNode::Handle::cast_dynamic(x)) { components[i]=x; return true; } Type &type(get_type()); if (type == type_vector) { if(x->get_type()==ValueBase(Real()).get_type() || PlaceholderValueNode::Handle::cast_dynamic(x)) { components[i]=x; return true; } } else if (type == type_color) { if(x->get_type()==ValueBase(Real()).get_type() || PlaceholderValueNode::Handle::cast_dynamic(x)) { components[i]=x; return true; } } else if (type == type_segment) { if(x->get_type()==ValueBase(Point()).get_type() || PlaceholderValueNode::Handle::cast_dynamic(x)) { components[i]=x; return true; } } else if (type == type_bline_point) { if((i==0 || i==4 || i==5) && x->get_type()==ValueBase(Point()).get_type()) { components[i]=x; return true; } if((i==1 || i==2) && x->get_type()==ValueBase(Real()).get_type()) { components[i]=x; return true; } if((i==3 || i==6 || i==7) && x->get_type()==ValueBase(bool()).get_type()) { components[i]=x; return true; } } else if (type == type_dash_item || type == type_width_point) { if((i==0 || i==1) && x->get_type()==ValueBase(Real()).get_type()) { components[i]=x; return true; } if((i==2 || i==3) && x->get_type()==ValueBase(int()).get_type()) { components[i]=x; return true; } if((i==4 || i==5) && x->get_type()==ValueBase(Real()).get_type()) { if(ValueNode_Const::Handle::cast_dynamic(x)) { if(i==4 && components[5]) { if(i==4 && (*x)(0).get(Real()) < (*components[5])(0).get(Real())) { components[i]=x; return true; } else return false; } if(i==5 && components[4]) { if((i==5 && (*x)(0).get(Real()) > (*components[4])(0).get(Real()))) { components[i]=x; return true; } else return false; } components[i]=x; return true; } return false; } } else if (type == type_transformation) { if( PlaceholderValueNode::Handle::cast_dynamic(x) || (i == 0 && x->get_type()==ValueBase(Vector()).get_type()) || (i == 1 && x->get_type()==ValueBase(Angle()).get_type()) || (i == 2 && x->get_type()==ValueBase(Angle()).get_type()) || (i == 3 && x->get_type()==ValueBase(Vector()).get_type()) ) { components[i]=x; return true; } } else if (dynamic_cast<types_namespace::TypeWeightedValueBase*>(&type) != NULL) { types_namespace::TypeWeightedValueBase *tp = dynamic_cast<types_namespace::TypeWeightedValueBase*>(&type); if( PlaceholderValueNode::Handle::cast_dynamic(x) || (i == 0 && x->get_type()==ValueBase(Real()).get_type()) || (i == 1 && x->get_type()==tp->get_contained_type()) ) { components[i]=x; return true; } } else if (dynamic_cast<types_namespace::TypePairBase*>(&type) != NULL) { types_namespace::TypePairBase *tp = dynamic_cast<types_namespace::TypePairBase*>(&type); if( PlaceholderValueNode::Handle::cast_dynamic(x) || (i == 0 && x->get_type()==tp->get_first_type()) || (i == 1 && x->get_type()==tp->get_second_type()) ) { components[i]=x; return true; } } return false; }
void synfigapp::recurse_valuedesc(synfigapp::ValueDesc h, const std::set<Time> &tlist, timepoints_ref &vals, synfig::Time time_offset, synfig::Real time_dilation) { //special cases for Animated, DynamicList, and Linkable //synfig::info("ValueBasenode... %p, %s", h.get_value_node().get(),typeid(*h.get_value_node()).name()); //animated case { synfig::ValueNode_Animated::Handle p = synfig::ValueNode_Animated::Handle::cast_dynamic(h.get_value_node()); if(p) { //loop through and determine which waypoint we will need to reference const synfig::WaypointList &w = p->waypoint_list(); synfig::WaypointList::const_iterator i = w.begin(), end = w.end(); std::set<Time>::const_iterator j = tlist.begin(), jend = tlist.end(); for(; i != end && j != jend;) { //synfig::info("tpair t(%.3f) = %.3f", (float)*j, (float)(i->get_time())); if((*j*time_dilation+time_offset).is_equal(i->get_time())) { vals.insert(p,*i,time_dilation); ++i,++j; }else if(*i < *j*time_dilation+time_offset) { ++i; }else ++j; } return; } } //parent dynamiclist case - just for active points for that object... if(h.parent_is_value_node()) { synfig::ValueNode_DynamicList::Handle p = synfig::ValueNode_DynamicList::Handle::cast_dynamic(h.get_parent_value_node()); if(p) { int index = h.get_index(); //check all the active points in each list... const synfig::ActivepointList &a = p->list[index].timing_info; //synfig::info("Our parent = dynamic list, searching in %d activepts",a.size()); std::set<Time>::const_iterator i = tlist.begin(), end = tlist.end(); synfig::ActivepointList::const_iterator j = a.begin(), jend = a.end(); for(; j != jend && i != end;) { double it = *i*time_dilation+time_offset; double jt = j->get_time(); double diff = (double)(it - jt); //synfig::info("\ttpair match(%.4lg) - %.4lg (diff = %lg",it,jt,diff); // if(abs(diff) < (double)Time::epsilon()) { //synfig::info("\tActivepoint to add being referenced (%x,%s,%.4lg)", // (int)j->get_uid(),j->state?"true":"false", (double)j->time); vals.insert(ValueDesc(p,index),*j,time_dilation); ++i,++j; }else if(it < jt) { ++i; //synfig::info("\tIncrementing time"); } else { ++j; //synfig::info("\tIncrementing actpt"); } } } } //dynamiclist case - we must still make sure that we read from the list entries the time values // because just the linked valuenodes will not do that { synfig::ValueNode_DynamicList::Handle p = synfig::ValueNode_DynamicList::Handle::cast_dynamic(h.get_value_node()); if(p) { //synfig::info("Process dynamic list valuenode"); int index = 0; std::vector<synfig::ValueNode_DynamicList::ListEntry>::const_iterator i = p->list.begin(), end = p->list.end(); for(; i != end; ++i, ++index) { const Node::time_set &tset = i->get_times(); if(check_intersect(tset.begin(),tset.end(),tlist.begin(),tlist.end(),time_offset,time_dilation)) { recurse_valuedesc(ValueDesc(p,index),tlist,vals,time_offset,time_dilation); } } return; } } //the linkable case... { etl::handle<synfig::LinkableValueNode> p = etl::handle<synfig::LinkableValueNode>::cast_dynamic(h.get_value_node()); if(p) { //synfig::info("Process Linkable ValueBasenode"); int i = 0, size = p->link_count(); for(; i < size; ++i) { ValueNode::Handle v = p->get_link(i); const Node::time_set &tset = v->get_times(); if(check_intersect(tset.begin(),tset.end(),tlist.begin(),tlist.end(),time_offset,time_dilation)) { recurse_valuedesc(ValueDesc(p,i),tlist,vals,time_offset,time_dilation); } } } } }