/* === S Y N F I G ========================================================= */
/*! \file valuenode_dynamiclist.cpp
-** \brief Template File
+** \brief Implementation of the "Dynamic List" valuenode conversion.
**
-** $Id: valuenode_dynamiclist.cpp,v 1.1.1.1 2005/01/04 01:23:15 darco Exp $
+** $Id$
**
** \legal
-** Copyright (c) 2002 Robert B. Quattlebaum Jr.
+** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+** Copyright (c) 2008 Chris Moore
**
-** This software and associated documentation
-** are CONFIDENTIAL and PROPRIETARY property of
-** the above-mentioned copyright holder.
+** This package is free software; you can redistribute it and/or
+** modify it under the terms of the GNU General Public License as
+** published by the Free Software Foundation; either version 2 of
+** the License, or (at your option) any later version.
**
-** You may not copy, print, publish, or in any
-** other way distribute this software without
-** a prior written agreement with
-** the copyright holder.
+** This package is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
** \endlegal
*/
/* ========================================================================= */
ValueNode_DynamicList::ListEntry::add(Time time, bool status, int priority)
{
typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList::iterator iterator;
-
+
//! \optimize
Activepoint ap(time,status,priority);
ap.set_parent_index(get_index());
timing_info.push_back(ap);
iterator iter(--iterator(timing_info.end()));
timing_info.sort();
-
+
return iter;
}
ValueNode_DynamicList::ListEntry::add(const Activepoint &x)
{
typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList::iterator iterator;
-
+
//! \optimize
Activepoint ap(x);
ap.set_parent_index(get_index());
timing_info.push_back(ap);
iterator iter(--iterator(timing_info.end()));
timing_info.sort();
-
+
return iter;
}
ValueNode_DynamicList::reindex()
{
int i(0);
-
+
std::vector<ListEntry>::iterator iter;
for(iter=list.begin();iter!=list.end();++iter)
iter2->set_parent_index(i);
iter2->set_parent_value_node(this);
}
- iter->index=i;
+ iter->index=i;
iter->set_parent_value_node(this);
}
}
ValueNode_DynamicList::create_list_entry(int index, Time time, Real origin)
{
ValueNode_DynamicList::ListEntry ret;
-
-
+
+
synfig::ValueBase prev,next;
index=index%link_count();
assert(index>=0);
-
+
ret.index=index;
ret.set_parent_value_node(this);
-
+
next=(*list[index].value_node)(time);
-
+
if(index!=0)
prev=(*list[index-1].value_node)(time);
else
prev=next;
}
}
-
-
+
+
switch(get_contained_type())
{
case ValueBase::TYPE_VECTOR:
break;
}
-
+
return ret;
}
ValueNode_DynamicList::ListEntry::find(const Time& x)
{
typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
-
+
ActivepointList::iterator iter;
for(iter=timing_info.begin();iter!=timing_info.end();++iter)
if(iter->time==x)
return iter;
- throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find():"+x.get_string());
+ throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find():"+x.get_string());
}
ValueNode_DynamicList::ListEntry::ActivepointList::const_iterator
ValueNode_DynamicList::ListEntry::find(const Time& x)const
{
typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
-
+
ActivepointList::const_iterator iter;
for(iter=timing_info.begin();iter!=timing_info.end();++iter)
if(iter->time==x)
return iter;
- throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find()const:"+x.get_string());
+ throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find()const:"+x.get_string());
}
ValueNode_DynamicList::ListEntry::ActivepointList::iterator
ValueNode_DynamicList::ListEntry::find_next(const Time& x)
{
typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
-
+
ActivepointList::iterator iter;
for(iter=timing_info.begin();iter!=timing_info.end();++iter)
if(iter->time>x)
return iter;
- throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_next():"+x.get_string());
+ throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_next():"+x.get_string());
}
ValueNode_DynamicList::ListEntry::ActivepointList::const_iterator
ValueNode_DynamicList::ListEntry::find_next(const Time& x)const
{
typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
-
+
ActivepointList::const_iterator iter;
for(iter=timing_info.begin();iter!=timing_info.end();++iter)
if(iter->time>x)
return iter;
- throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_next()const:"+x.get_string());
+ throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_next()const:"+x.get_string());
}
ValueNode_DynamicList::ListEntry::ActivepointList::iterator
ValueNode_DynamicList::ListEntry::find_prev(const Time& x)
{
typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
-
+
ActivepointList::iterator iter;
iter=timing_info.end();
do
}
while(iter!=timing_info.begin());
- throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_prev():"+x.get_string());
+ throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_prev():"+x.get_string());
}
ValueNode_DynamicList::ListEntry::ActivepointList::const_iterator
ValueNode_DynamicList::ListEntry::find_prev(const Time& x)const
{
typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
-
+
ActivepointList::const_iterator iter;
iter=timing_info.end();
do
}
while(iter!=timing_info.begin());
- throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_prev()const:"+x.get_string());
+ throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_prev()const:"+x.get_string());
}
int
{
Time curr_time(begin);
int ret(0);
-
+
// try to grab first waypoint
try
{
ret++;
}
catch(...) { }
-
+
try
{
ActivepointList::iterator iter;
}
}
catch(...) { }
-
+
return ret;
}
{
typedef synfig::ValueNode_DynamicList::ListEntry::Activepoint Activepoint;
typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
-
+
if(timing_info.empty())
return 1.0f;
-
+
try
{
ActivepointList::const_iterator iter;
try { prev_iter=find_prev(t); }
catch(...) { return find_next(t)->state?1.0f:0.0f; }
-
+
try { next_iter=find_next(t); }
catch(...) { return prev_iter->state?1.0f:0.0f; }
-
+
if(next_iter->state==prev_iter->state)
return next_iter->state?1.0f:0.0f;
-
+
if(rising)*rising=next_iter->state;
if(next_iter->state==true)
ValueNode_DynamicList::ListEntry::new_activepoint_at_time(const Time& time)const
{
Activepoint activepoint;
-
+
activepoint.set_state(status_at_time(time));
activepoint.set_priority(0);
-
+
return activepoint;
}
{
typedef synfig::ValueNode_DynamicList::ListEntry::Activepoint Activepoint;
typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
-
+
ActivepointList::const_iterator entry_iter;
ActivepointList::const_iterator prev_iter;
bool state(true);
- // New "symetric" state mechanism
+ // New "symmetric" state mechanism
if(!timing_info.empty())
{
if(timing_info.size()==1)
}
if(entry_iter->time>t)
break;
-
+
}
prev_iter=entry_iter;
prev_iter--;
-
+
// ie:
//
// |-------|---t---|-------|
// prev_iter^ ^entry_iter
-
+
if(entry_iter==timing_info.end())
{
state=prev_iter->state;
}
else
{
- state=prev_iter->state;
- }
+ state=prev_iter->state;
+ }
}
}
return state;
{
ListEntry list_entry(value_node);
list_entry.timing_info.size();
-
+
if(index<0 || index>=(int)list.size())
{
list.push_back(list_entry);
ValueNode_DynamicList::erase(const ValueNode::Handle &value_node_)
{
ValueNode::Handle value_node(value_node_);
-
+
assert(value_node);
if(!value_node)
throw String("ValueNode_DynamicList::erase(): Passed bad value node");
-
+
std::vector<ListEntry>::iterator iter;
for(iter=list.begin();iter!=list.end();++iter)
if(iter->value_node==value_node)
if(value_node)
{
remove_child(value_node.get());
- if(get_parent_canvas())
- get_parent_canvas()->signal_value_node_child_removed()(this,value_node);
- else if(get_root_canvas() && get_parent_canvas())
+ // changed to fix bug 1420091 - it seems that when a .sif file containing a bline layer encapsulated inside
+ // another layer, get_parent_canvas() is false and get_root_canvas() is true, but when we come to erase a
+ // vertex, both are true. So the signal is sent to the parent, but the signal wasn't sent to the parent
+ // when it was added. This probably isn't the right fix, but it seems to work for now. Note that the same
+ // strange "if (X) else if (Y && X)" code is also present in the two previous functions, above.
+
+ // if(get_parent_canvas())
+ // get_parent_canvas()->signal_value_node_child_removed()(this,value_node);
+ // else if(get_root_canvas() && get_parent_canvas())
+ // get_root_canvas()->signal_value_node_child_removed()(this,value_node);
+ if(get_root_canvas())
get_root_canvas()->signal_value_node_child_removed()(this,value_node);
}
break;
if(value_list.empty())
return 0;
-
+
ValueNode_DynamicList* value_node(new ValueNode_DynamicList(value_list.front().get_type()));
-
+
+ // when creating a list of vectors, start it off being looped.
+ // I think the only time this is used if for creating polygons,
+ // and we want them to be looped by default
+ if (value_node->get_contained_type() == ValueBase::TYPE_VECTOR)
+ value_node->set_loop(true);
+
for(iter=value_list.begin();iter!=value_list.end();++iter)
{
ValueNode::Handle item(ValueNode_Const::create(*iter));
for(iter=list.begin();iter!=list.end();++iter)
{
bool state(iter->status_at_time(t));
-
+
if(state)
{
if(iter->value_node->get_type()==container_type)
}
}
}
-
+
if(list.empty())
synfig::warning(string("ValueNode_DynamicList::operator()():")+_("No entries in list"));
else
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)
ValueNode_DynamicList::get_link_vfunc(int i)const
{
assert(i>=0);
+
if((unsigned)i>=list.size())
return 0;
return list[i].value_node;
String
ValueNode_DynamicList::link_local_name(int i)const
{
- assert(i>=0 && (unsigned)i<list.size());
+ assert(i>=0 && i<link_count());
+
return etl::strprintf(_("Item %03d"),i+1);
-}
+}
ValueNode*
ValueNode_DynamicList::clone(const GUID& deriv_guid)const
{
{ ValueNode* x(find_value_node(get_guid()^deriv_guid).get()); if(x)return x; }
- ValueNode_DynamicList* ret=new ValueNode_DynamicList(container_type);
+ ValueNode_DynamicList* ret=dynamic_cast<ValueNode_DynamicList*>(create_new());
ret->set_guid(get_guid()^deriv_guid);
std::vector<ListEntry>::const_iterator iter;
if(iter->value_node->is_exported())
ret->add(*iter);
else
- {
+ {
ListEntry list_entry(*iter);
//list_entry.value_node=find_value_node(iter->value_node->get_guid()^deriv_guid).get();
//if(!list_entry.value_node)
- list_entry.value_node=iter->value_node->clone(deriv_guid);
+ list_entry.value_node=iter->value_node->clone(deriv_guid);
ret->add(list_entry);
//ret->list.back().value_node=iter->value_node.clone();
}
return type==ValueBase::TYPE_LIST;
}
+void
+ValueNode_DynamicList::set_member_canvas(etl::loose_handle<Canvas> canvas)
+{
+ for (vector<ListEntry>::iterator iter = list.begin(); iter != list.end(); iter++)
+ iter->value_node->set_parent_canvas(canvas);
+}
+
ValueBase::Type
ValueNode_DynamicList::get_contained_type()const
{
LinkableValueNode*
ValueNode_DynamicList::create_new()const
{
- assert(0);
- return 0;
+ return new ValueNode_DynamicList(container_type);
}
int
ValueNode_DynamicList::find_next_valid_entry(int orig_item, Time t)const
{
int curr_item;
-
+
for(curr_item=orig_item+1;curr_item!=orig_item;curr_item++)
{
if(curr_item==(int)list.size())
ValueNode_DynamicList::find_prev_valid_entry(int orig_item, Time t)const
{
int curr_item;
-
+
for(curr_item=orig_item-1;curr_item!=orig_item;curr_item--)
{
if(curr_item==-1)
{
synfig::ActivepointList::const_iterator j = timing_info.begin(),
end = timing_info.end();
-
+
//must remerge with all the other values because we don't know if we've changed...
times = value_node->get_times();
-
+
for(; j != end; ++j)
{
TimePoint t;
times.insert(t);
}
-
+
return times;
}
{
//add in the active points
int size = list.size();
-
+
//rebuild all the info...
for(int i = 0; i < size; ++i)
{
{
findresult f;
f.second = false;
-
+
f.first = std::find(timing_info.begin(),timing_info.end(),x);
-
+
if(f.first != timing_info.end())
{
f.second = true;
}
-
+
return f;
}
{
const_findresult f;
f.second = false;
-
+
f.first = std::find(timing_info.begin(),timing_info.end(),x);
-
+
if(f.first != timing_info.end())
{
f.second = true;
}
-
+
return f;
}
{
findresult f;
f.second = false;
-
+
f.first = std::find_if(timing_info.begin(),timing_info.end(),timecmp(x));
-
+
if(f.first != timing_info.end())
{
f.second = true;
}
-
+
return f;
}
{
const_findresult f;
f.second = false;
-
+
f.first = std::find_if(timing_info.begin(),timing_info.end(),timecmp(x));
-
+
if(f.first != timing_info.end())
{
f.second = true;
}
-
+
return f;
}
try
{
ListEntry& item(*iter);
-
+
ActivepointList::iterator iter(item.find_next(location));
for(;iter!=item.timing_info.end();++iter)
{