bool Action::ValueDescLink::set_param(const synfig::String& name, const Action::Param ¶m) { if(name=="time" && param.get_type()==Param::TYPE_TIME) { time=param.get_time(); return true; } // don't bother looking for the best value to use if there's already been an error if (poison==true) return false; if(name=="value_desc" && param.get_type()==Param::TYPE_VALUEDESC) { ValueDesc value_desc(param.get_value_desc()); // If we are handling a Composite WidthPoint then use its position as param if(value_desc.is_value_node() && value_desc.parent_is_linkable_value_node()) { synfig::ValueNode_Composite::Handle compo(synfig::ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node())); if(compo) { String param_name; if (value_desc.parent_is_value_desc() && !value_desc.get_sub_name().empty()) { LinkableValueNode::Vocab vocab = compo->get_children_vocab(); for(LinkableValueNode::Vocab::const_iterator i = vocab.begin(); i != vocab.end(); ++i) if (i->get_name() == value_desc.get_sub_name()) param_name = value_desc.get_sub_name(); } //! Test used for with point handle if (param_name.empty() && compo->get_type() == type_width_point) param_name = "position"; if (param_name.empty() && compo->get_type() == type_bline_point) param_name = "point"; if ( compo->get_type() == type_bline_point && param_name == "t2" && (*compo)(time).get(BLinePoint()).get_merge_tangent_both()) { param_name = "t1"; } if (!param_name.empty()) { synfigapp::Action::Param param(synfigapp::ValueDesc(compo, compo->get_link_index_from_name(param_name))); return set_param("value_desc", param); } } } if(value_desc.is_value_node() && value_desc.get_value_node()->is_exported()) { if(link_value_node==value_desc.get_value_node()) return true; if(link_value_node && link_value_node->is_exported()) { poison=true; status_message = (_("Cannot link two different exported values ('") + value_desc.get_value_node()->get_id() + _("' and '") + link_value_node->get_id()) + _("')"); return false; } link_value_node=value_desc.get_value_node(); link_scalar=value_desc.parent_is_linkable_value_node()?value_desc.get_scalar():1.0; status_message = _("Used exported ValueNode ('") + link_value_node->get_id() + _("')."); } else if(value_desc.is_value_node()) { if(!link_value_node) { status_level = 1; status_message = _("Using the only available ValueNode."); link_value_node=value_desc.get_value_node(); link_scalar=value_desc.parent_is_linkable_value_node()?value_desc.get_scalar():1.0; } else if(link_value_node->is_exported()) { // we've already seen an exported value, so use that rather than the current value } // Use the one that is referenced more else if(link_value_node->rcount()!=value_desc.get_value_node()->rcount()) { if(link_value_node->rcount()<value_desc.get_value_node()->rcount()) { status_level = 2; status_message = _("Using the most referenced ValueNode."); link_value_node=value_desc.get_value_node(); link_scalar=value_desc.parent_is_linkable_value_node()?value_desc.get_scalar():1.0; } else if (status_level <= 2) { status_level = 2; status_message = _("Using the most referenced ValueNode."); } } // If the current link value node is a constant and // this one isn't, then give preference to the exotic else if(ValueNode_Const::Handle::cast_dynamic(link_value_node) && !ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node())) { status_level = 3; status_message = _("There's a tie for most referenced; using the animated ValueNode."); link_value_node=value_desc.get_value_node(); link_scalar=value_desc.parent_is_linkable_value_node()?value_desc.get_scalar():1.0; } else if(ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node()) && !ValueNode_Const::Handle::cast_dynamic(link_value_node)) { if (status_level <= 3) { status_level = 3; status_message = _("There's a tie for most referenced; using the animated ValueNode."); } } // If both are animated, and this one has more waypoints, then use the one with more waypoints else if(ValueNode_Animated::Handle::cast_dynamic(link_value_node) && ValueNode_Animated::Handle::cast_dynamic(value_desc.get_value_node()) && ValueNode_Animated::Handle::cast_dynamic(link_value_node)->waypoint_list().size() != ValueNode_Animated::Handle::cast_dynamic(value_desc.get_value_node())->waypoint_list().size()) { if (ValueNode_Animated::Handle::cast_dynamic(link_value_node)->waypoint_list().size() < ValueNode_Animated::Handle::cast_dynamic(value_desc.get_value_node())->waypoint_list().size()) { status_level = 4; status_message = _("There's a tie for most referenced, and both are animated; using the one with the most waypoints."); link_value_node=value_desc.get_value_node(); link_scalar=value_desc.parent_is_linkable_value_node()?value_desc.get_scalar():1.0; } else if (status_level <= 4) { status_level = 4; status_message = _("There's a tie for most referenced, and both are animated; using the one with the most waypoints."); } } // If both are Linkable Value Nodes and has waypoint in its children, use the one with more waypoints else if(LinkableValueNode::Handle::cast_dynamic(link_value_node) && LinkableValueNode::Handle::cast_dynamic(value_desc.get_value_node()) && LinkableValueNode::Handle::cast_dynamic(link_value_node)->get_times().size() != LinkableValueNode::Handle::cast_dynamic(value_desc.get_value_node())->get_times().size()) { if(LinkableValueNode::Handle::cast_dynamic(link_value_node)->get_times().size() < LinkableValueNode::Handle::cast_dynamic(value_desc.get_value_node())->get_times().size()) { status_level = 4; status_message = _("There's a tie for most referenced, and both are linkable value node animated; using the one with the most waypoints."); link_value_node=value_desc.get_value_node(); link_scalar=value_desc.parent_is_linkable_value_node()?value_desc.get_scalar():1.0; } else if (status_level <= 4) { status_level = 4; status_message = _("There's a tie for most referenced, and both are linkable value node animated; using the one with the most waypoints."); } } // Use the one that was least recently changed else if(link_value_node->get_time_last_changed()!=value_desc.get_value_node()->get_time_last_changed()) { if(link_value_node->get_time_last_changed()>value_desc.get_value_node()->get_time_last_changed()) { status_level = 5; status_message = _("Everything is tied; using the least recently modified value."); link_value_node=value_desc.get_value_node(); link_scalar=value_desc.parent_is_linkable_value_node()?value_desc.get_scalar():1.0; } else if (status_level <= 5) { status_level = 5; status_message = _("Everything is tied; using the least recently modified value."); } } else { status_level = 6; status_message = _("Absolutely everything is tied."); } } if(value_desc_list.size() && value_desc.get_value_type()!=value_desc_list.front().get_value_type()) { // Everything must be of the same type poison=true; status_message = (strprintf(_("Cannot link two values of different types ('%s' and '%s')"), value_desc.get_value_type().description.local_name.c_str(), value_desc_list.front().get_value_type().description.local_name.c_str())); return false; } value_desc_list.push_back(value_desc); return true; } return Action::CanvasSpecific::set_param(name,param); }