1 /* === S I N F G =========================================================== */
2 /*! \file valuenode_dynamiclist.cpp
3 ** \brief Template File
5 ** $Id: valuenode_dynamiclist.cpp,v 1.1.1.1 2005/01/04 01:23:15 darco Exp $
8 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
10 ** This software and associated documentation
11 ** are CONFIDENTIAL and PROPRIETARY property of
12 ** the above-mentioned copyright holder.
14 ** You may not copy, print, publish, or in any
15 ** other way distribute this software without
16 ** a prior written agreement with
17 ** the copyright holder.
20 /* ========================================================================= */
22 /* === H E A D E R S ======================================================= */
31 #include "valuenode_dynamiclist.h"
32 #include "valuenode_const.h"
33 #include "valuenode_composite.h"
35 #include "exception.h"
43 /* === U S I N G =========================================================== */
47 using namespace sinfg;
49 /* === M A C R O S ========================================================= */
51 /* === G L O B A L S ======================================================= */
53 /* === P R O C E D U R E S ================================================= */
55 /* === M E T H O D S ======================================================= */
57 ValueNode_DynamicList::ListEntry::ListEntry():
62 ValueNode_DynamicList::ListEntry::ListEntry(const ValueNode::Handle &value_node):
63 value_node(value_node),
68 ValueNode_DynamicList::ListEntry::ListEntry(const ValueNode::Handle &value_node,Time begin, Time end):
69 value_node(value_node)
73 add((begin+end)*0.5,true);
76 ValueNode_DynamicList::ListEntry::ActivepointList::iterator
77 ValueNode_DynamicList::ListEntry::add(Time time, bool status, int priority)
79 typedef sinfg::ValueNode_DynamicList::ListEntry::ActivepointList::iterator iterator;
82 Activepoint ap(time,status,priority);
83 ap.set_parent_index(get_index());
84 ap.set_parent_value_node(get_parent_value_node());
85 timing_info.push_back(ap);
86 iterator iter(--iterator(timing_info.end()));
92 ValueNode_DynamicList::ListEntry::ActivepointList::iterator
93 ValueNode_DynamicList::ListEntry::add(const Activepoint &x)
95 typedef sinfg::ValueNode_DynamicList::ListEntry::ActivepointList::iterator iterator;
99 ap.set_parent_index(get_index());
100 ap.set_parent_value_node(get_parent_value_node());
101 timing_info.push_back(ap);
102 iterator iter(--iterator(timing_info.end()));
109 ValueNode_DynamicList::reindex()
113 std::vector<ListEntry>::iterator iter;
115 for(iter=list.begin();iter!=list.end();++iter)
117 assert(iter->value_node);
118 if(iter->index!=i || iter->get_parent_value_node().get()!=this)
120 ActivepointList::iterator iter2;
122 if(iter->timing_info.size()) // is this line really necessary?
123 for(iter2=iter->timing_info.begin();iter2!=iter->timing_info.end();++iter2)
125 iter2->set_parent_index(i);
126 iter2->set_parent_value_node(this);
129 iter->set_parent_value_node(this);
134 ValueNode_DynamicList::ListEntry
135 ValueNode_DynamicList::create_list_entry(int index, Time time, Real origin)
137 ValueNode_DynamicList::ListEntry ret;
140 sinfg::ValueBase prev,next;
142 index=index%link_count();
147 ret.set_parent_value_node(this);
149 next=(*list[index].value_node)(time);
152 prev=(*list[index-1].value_node)(time);
156 prev=(*list[link_count()-1].value_node)(time);
164 switch(get_contained_type())
166 case ValueBase::TYPE_VECTOR:
168 Vector a(prev.get(Vector())), b(next.get(Vector()));
169 ret.value_node=ValueNode_Const::create((b-a)*origin+a);
172 case ValueBase::TYPE_REAL:
174 Real a(prev.get(Real())), b(next.get(Real()));
175 ret.value_node=ValueNode_Const::create((b-a)*origin+a);
178 case ValueBase::TYPE_COLOR:
180 Color a(prev.get(Color())), b(next.get(Color()));
181 ret.value_node=ValueNode_Composite::create((b-a)*origin+a);
184 case ValueBase::TYPE_ANGLE:
186 Angle a(prev.get(Angle())), b(next.get(Angle()));
187 ret.value_node=ValueNode_Const::create((b-a)*origin+a);
190 case ValueBase::TYPE_TIME:
192 Time a(prev.get(Time())), b(next.get(Time()));
193 ret.value_node=ValueNode_Const::create((b-a)*origin+a);
197 ret.value_node=ValueNode_Const::create(get_contained_type());
205 ValueNode_DynamicList::ListEntry::ActivepointList::iterator
206 ValueNode_DynamicList::ListEntry::find(const UniqueID& x)
208 return std::find(timing_info.begin(),timing_info.end(),x);
211 ValueNode_DynamicList::ListEntry::ActivepointList::const_iterator
212 ValueNode_DynamicList::ListEntry::find(const UniqueID& x)const
214 return std::find(timing_info.begin(),timing_info.end(),x);
218 ValueNode_DynamicList::ListEntry::erase(const UniqueID& x)
220 timing_info.erase(find(x));
223 ValueNode_DynamicList::ListEntry::ActivepointList::iterator
224 ValueNode_DynamicList::ListEntry::find(const Time& x)
226 typedef sinfg::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
228 ActivepointList::iterator iter;
230 for(iter=timing_info.begin();iter!=timing_info.end();++iter)
234 throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find():"+x.get_string());
237 ValueNode_DynamicList::ListEntry::ActivepointList::const_iterator
238 ValueNode_DynamicList::ListEntry::find(const Time& x)const
240 typedef sinfg::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
242 ActivepointList::const_iterator iter;
244 for(iter=timing_info.begin();iter!=timing_info.end();++iter)
248 throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find()const:"+x.get_string());
251 ValueNode_DynamicList::ListEntry::ActivepointList::iterator
252 ValueNode_DynamicList::ListEntry::find_next(const Time& x)
254 typedef sinfg::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
256 ActivepointList::iterator iter;
258 for(iter=timing_info.begin();iter!=timing_info.end();++iter)
262 throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_next():"+x.get_string());
265 ValueNode_DynamicList::ListEntry::ActivepointList::const_iterator
266 ValueNode_DynamicList::ListEntry::find_next(const Time& x)const
268 typedef sinfg::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
270 ActivepointList::const_iterator iter;
272 for(iter=timing_info.begin();iter!=timing_info.end();++iter)
276 throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_next()const:"+x.get_string());
279 ValueNode_DynamicList::ListEntry::ActivepointList::iterator
280 ValueNode_DynamicList::ListEntry::find_prev(const Time& x)
282 typedef sinfg::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
284 ActivepointList::iterator iter;
285 iter=timing_info.end();
292 while(iter!=timing_info.begin());
294 throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_prev():"+x.get_string());
297 ValueNode_DynamicList::ListEntry::ActivepointList::const_iterator
298 ValueNode_DynamicList::ListEntry::find_prev(const Time& x)const
300 typedef sinfg::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
302 ActivepointList::const_iterator iter;
303 iter=timing_info.end();
310 while(iter!=timing_info.begin());
312 throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_prev()const:"+x.get_string());
316 ValueNode_DynamicList::ListEntry::find(const Time& begin,const Time& end,std::vector<Activepoint*>& selected)
318 Time curr_time(begin);
321 // try to grab first waypoint
324 ActivepointList::iterator iter;
325 iter=find(curr_time);
326 selected.push_back(&*iter);
333 ActivepointList::iterator iter;
336 iter=find_next(curr_time);
337 curr_time=iter->get_time();
340 selected.push_back(&*iter);
350 ValueNode_DynamicList::ListEntry::amount_at_time(const Time &t,bool *rising)const
352 typedef sinfg::ValueNode_DynamicList::ListEntry::Activepoint Activepoint;
353 typedef sinfg::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
355 if(timing_info.empty())
360 ActivepointList::const_iterator iter;
362 return iter->state?1.0f:0.0f;
366 ActivepointList::const_iterator prev_iter;
367 ActivepointList::const_iterator next_iter;
369 try { prev_iter=find_prev(t); }
370 catch(...) { return find_next(t)->state?1.0f:0.0f; }
372 try { next_iter=find_next(t); }
373 catch(...) { return prev_iter->state?1.0f:0.0f; }
375 if(next_iter->state==prev_iter->state)
376 return next_iter->state?1.0f:0.0f;
378 if(rising)*rising=next_iter->state;
380 if(next_iter->state==true)
381 return float((t-prev_iter->time)/(next_iter->time-prev_iter->time));
383 return float((next_iter->time-t)/(next_iter->time-prev_iter->time));
387 ValueNode_DynamicList::ListEntry::new_activepoint_at_time(const Time& time)const
389 Activepoint activepoint;
391 activepoint.set_state(status_at_time(time));
392 activepoint.set_priority(0);
398 ValueNode_DynamicList::ListEntry::status_at_time(const Time &t)const
400 typedef sinfg::ValueNode_DynamicList::ListEntry::Activepoint Activepoint;
401 typedef sinfg::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
403 ActivepointList::const_iterator entry_iter;
404 ActivepointList::const_iterator prev_iter;
407 // New "symetric" state mechanism
408 if(!timing_info.empty())
410 if(timing_info.size()==1)
411 state=timing_info.front().state;
414 //! \optimize Perhaps we should use a binary search...?
415 // This will give us the first activepoint that is after t.
416 for(entry_iter=timing_info.begin();entry_iter!=timing_info.end();++entry_iter)
418 if(entry_iter->time==t)
420 // If we hit the entry right on the nose, then we don't
421 // have to do anything more
422 return entry_iter->state;
424 if(entry_iter->time>t)
428 prev_iter=entry_iter;
433 // |-------|---t---|-------|
434 // prev_iter^ ^entry_iter
436 if(entry_iter==timing_info.end())
438 state=prev_iter->state;
441 if(entry_iter==timing_info.begin())
443 state=entry_iter->state;
446 if(entry_iter->priority==prev_iter->priority)
448 state=entry_iter->state || prev_iter->state;
451 if(entry_iter->priority>prev_iter->priority)
453 state=entry_iter->state;
457 state=prev_iter->state;
468 ValueNode_DynamicList::add(const ValueNode::Handle &value_node, int index)
470 ListEntry list_entry(value_node);
471 list_entry.timing_info.size();
473 if(index<0 || index>=(int)list.size())
475 list.push_back(list_entry);
479 list.insert(list.begin()+index,list_entry);
482 add_child(value_node.get());
486 if(get_parent_canvas())
487 get_parent_canvas()->signal_value_node_child_added()(this,value_node);
488 else if(get_root_canvas() && get_parent_canvas())
489 get_root_canvas()->signal_value_node_child_added()(this,value_node);
493 ValueNode_DynamicList::add(const ListEntry &list_entry, int index)
495 if(index<0 || index>=(int)list.size())
496 list.push_back(list_entry);
498 list.insert(list.begin()+index,list_entry);
499 add_child(list_entry.value_node.get());
504 if(get_parent_canvas())
505 get_parent_canvas()->signal_value_node_child_added()(this,list_entry.value_node);
506 else if(get_root_canvas() && get_parent_canvas())
507 get_root_canvas()->signal_value_node_child_added()(this,list_entry.value_node);
511 ValueNode_DynamicList::erase(const ValueNode::Handle &value_node_)
513 ValueNode::Handle value_node(value_node_);
517 throw String("ValueNode_DynamicList::erase(): Passed bad value node");
519 std::vector<ListEntry>::iterator iter;
520 for(iter=list.begin();iter!=list.end();++iter)
521 if(iter->value_node==value_node)
526 remove_child(value_node.get());
527 if(get_parent_canvas())
528 get_parent_canvas()->signal_value_node_child_removed()(this,value_node);
529 else if(get_root_canvas() && get_parent_canvas())
530 get_root_canvas()->signal_value_node_child_removed()(this,value_node);
538 ValueNode_DynamicList::ValueNode_DynamicList(ValueBase::Type container_type):
539 LinkableValueNode(ValueBase::TYPE_LIST),
540 container_type (container_type),
546 ValueNode_DynamicList::Handle
547 ValueNode_DynamicList::create(ValueBase::Type id)
549 return new ValueNode_DynamicList(id);
552 ValueNode_DynamicList::~ValueNode_DynamicList()
557 ValueNode_DynamicList*
558 ValueNode_DynamicList::create_from(const ValueBase &value)
560 //vector<ValueBase> value_list(value.operator vector<ValueBase>());
561 vector<ValueBase> value_list(value.get_list());
563 vector<ValueBase>::iterator iter;
565 if(value_list.empty())
568 ValueNode_DynamicList* value_node(new ValueNode_DynamicList(value_list.front().get_type()));
570 for(iter=value_list.begin();iter!=value_list.end();++iter)
572 ValueNode::Handle item(ValueNode_Const::create(*iter));
573 value_node->add(ListEntry(item));
574 assert(value_node->list.back().value_node);
580 ValueNode_DynamicList::operator()(Time t)const
582 std::vector<ValueBase> ret_list;
583 std::vector<ListEntry>::const_iterator iter;
585 assert(container_type);
587 for(iter=list.begin();iter!=list.end();++iter)
589 bool state(iter->status_at_time(t));
593 if(iter->value_node->get_type()==container_type)
594 ret_list.push_back((*iter->value_node)(t));
597 sinfg::warning(string("ValueNode_DynamicList::operator()():")+_("List type/item type mismatch, throwing away mismatch"));
603 sinfg::warning(string("ValueNode_DynamicList::operator()():")+_("No entries in list"));
606 sinfg::warning(string("ValueNode_DynamicList::operator()():")+_("No entries in ret_list"));
612 ValueNode_DynamicList::set_link_vfunc(int i,ValueNode::Handle x)
615 if((unsigned)i>=list.size())
617 if(x->get_type()!=container_type)
619 list[i].value_node=x;
623 ValueNode::LooseHandle
624 ValueNode_DynamicList::get_link_vfunc(int i)const
627 if((unsigned)i>=list.size())
629 return list[i].value_node;
633 ValueNode_DynamicList::link_count()const
639 ValueNode_DynamicList::link_local_name(int i)const
641 assert(i>=0 && (unsigned)i<list.size());
642 return etl::strprintf(_("Item %03d"),i+1);
646 ValueNode_DynamicList::clone(const GUID& deriv_guid)const
648 { ValueNode* x(find_value_node(get_guid()^deriv_guid).get()); if(x)return x; }
650 ValueNode_DynamicList* ret=new ValueNode_DynamicList(container_type);
651 ret->set_guid(get_guid()^deriv_guid);
653 std::vector<ListEntry>::const_iterator iter;
655 for(iter=list.begin();iter!=list.end();++iter)
657 if(iter->value_node->is_exported())
661 ListEntry list_entry(*iter);
662 //list_entry.value_node=find_value_node(iter->value_node->get_guid()^deriv_guid).get();
663 //if(!list_entry.value_node)
664 list_entry.value_node=iter->value_node->clone(deriv_guid);
665 ret->add(list_entry);
666 //ret->list.back().value_node=iter->value_node.clone();
669 ret->set_loop(get_loop());
674 ValueNode_DynamicList::link_name(int i)const
676 return strprintf("item%04d",i);
680 ValueNode_DynamicList::get_link_index_from_name(const String &name)const
682 throw Exception::BadLinkName(name);
686 ValueNode_DynamicList::get_name()const
688 return "dynamic_list";
692 ValueNode_DynamicList::get_local_name()const
694 return _("Dynamic List");
698 ValueNode_DynamicList::check_type(ValueBase::Type type)
700 return type==ValueBase::TYPE_LIST;
704 ValueNode_DynamicList::get_contained_type()const
706 return container_type;
710 ValueNode_DynamicList::create_new()const
717 ValueNode_DynamicList::find_next_valid_entry(int orig_item, Time t)const
721 for(curr_item=orig_item+1;curr_item!=orig_item;curr_item++)
723 if(curr_item==(int)list.size())
728 if(list[curr_item].status_at_time(t))
735 ValueNode_DynamicList::find_prev_valid_entry(int orig_item, Time t)const
739 for(curr_item=orig_item-1;curr_item!=orig_item;curr_item--)
743 curr_item=list.size();
746 if(list[curr_item].status_at_time(t))
752 const sinfg::Node::time_set & ValueNode_DynamicList::ListEntry::get_times() const
754 sinfg::ActivepointList::const_iterator j = timing_info.begin(),
755 end = timing_info.end();
757 //must remerge with all the other values because we don't know if we've changed...
758 times = value_node->get_times();
763 t.set_time(j->get_time());
764 t.set_guid(j->get_guid());
772 void ValueNode_DynamicList::get_times_vfunc(Node::time_set &set) const
774 //add in the active points
775 int size = list.size();
777 //rebuild all the info...
778 for(int i = 0; i < size; ++i)
780 const Node::time_set & tset= list[i].get_times();
781 set.insert(tset.begin(),tset.end());
786 //new find functions that don't throw
791 timecmp(const Time &c) :t(c) {}
793 bool operator()(const Activepoint &rhs) const
795 return t.is_equal(rhs.get_time());
799 ValueNode_DynamicList::ListEntry::findresult ValueNode_DynamicList::ListEntry::find_uid(const UniqueID& x)
804 f.first = std::find(timing_info.begin(),timing_info.end(),x);
806 if(f.first != timing_info.end())
814 ValueNode_DynamicList::ListEntry::const_findresult ValueNode_DynamicList::ListEntry::find_uid(const UniqueID& x) const
819 f.first = std::find(timing_info.begin(),timing_info.end(),x);
821 if(f.first != timing_info.end())
829 ValueNode_DynamicList::ListEntry::findresult ValueNode_DynamicList::ListEntry::find_time(const Time& x)
834 f.first = std::find_if(timing_info.begin(),timing_info.end(),timecmp(x));
836 if(f.first != timing_info.end())
844 ValueNode_DynamicList::ListEntry::const_findresult ValueNode_DynamicList::ListEntry::find_time(const Time& x)const
849 f.first = std::find_if(timing_info.begin(),timing_info.end(),timecmp(x));
851 if(f.first != timing_info.end())
860 ValueNode_DynamicList::insert_time(const Time& location, const Time& delta)
865 std::vector<ListEntry>::iterator iter(list.begin());
866 for(;iter!=list.end();++iter)
870 ListEntry& item(*iter);
872 ActivepointList::iterator iter(item.find_next(location));
873 for(;iter!=item.timing_info.end();++iter)
875 iter->set_time(iter->get_time()+delta);
878 catch(Exception::NotFound) { }