--- /dev/null
+/* === S I N F G =========================================================== */
+/*! \file valuenode_dynamiclist.h
+** \brief Template Header
+**
+** $Id: valuenode_dynamiclist.h,v 1.1.1.1 2005/01/04 01:23:15 darco Exp $
+**
+** \legal
+** Copyright (c) 2002 Robert B. Quattlebaum Jr.
+**
+** This software and associated documentation
+** are CONFIDENTIAL and PROPRIETARY property of
+** the above-mentioned copyright holder.
+**
+** You may not copy, print, publish, or in any
+** other way distribute this software without
+** a prior written agreement with
+** the copyright holder.
+** \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SINFG_VALUENODE_DYNAMICLIST_H
+#define __SINFG_VALUENODE_DYNAMICLIST_H
+
+/* === H E A D E R S ======================================================= */
+
+#include <vector>
+#include <list>
+
+#include "valuenode.h"
+#include "time.h"
+#include "uniqueid.h"
+#include "activepoint.h"
+
+/* === M A C R O S ========================================================= */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace sinfg {
+class ValueNode_BLine;
+
+/*! \class ValueNode_DynamicList
+** \brief Animated List ValueNode
+**
+** This ValueNode was originaly set up to have a list
+** of ValueNodes and their associated "on" and "off" points.
+** ie: Any time that was directly after an "on" point,
+** the item would be "on", and any time that was directly
+** after an "off" point would be "off". This is pretty intuitive.
+** However, it does have it's problems.
+**
+** The problems arrise when we introduce the concept of a
+** Keyframe. Keyframes can be manipulated via the Sinfg
+** Application Library. They allow the user to quickly
+** and "automagickly" rearange an animation by moving
+** the associated keyframes. With they old way that the
+** "on" and "off" points were handled, this task became
+** overly complicated.
+**
+** What is required is a "symetric" system of describing
+** "on" and "off" points. Instead of the point representing
+** the state of the item after that point in time, we have
+** the point represent <i>only that frame</i>. The state
+** of the item is calculated by looking at the points
+** around it: If either (or both) points are "on", then the
+** current state is "on". Otherwise, the point is "off"
+**
+** This may be a bit confusing at first, but it is required
+** if we want the keyframe mechanism to "just work".
+*/
+class ValueNode_DynamicList : public LinkableValueNode
+{
+public:
+
+ /*! \class ListEntry
+ ** \brief Contains a potential list item, and associated timing information
+ **
+ ** This structure contains a RHandle to a ValueNode,
+ ** as well as the associated on/off timing information
+ ** which determines when this item is included in the list.
+ **
+ ** The timing information is stored in the member <tt>timing_info</tt>.
+ */
+ struct ListEntry : public UniqueID
+ {
+ friend class ValueNode_DynamicList;
+ friend class ValueNode_BLine;
+ public:
+ typedef sinfg::Activepoint Activepoint;
+
+ typedef std::list<Activepoint> ActivepointList;
+
+ typedef std::pair<ActivepointList::iterator,bool> findresult;
+ typedef std::pair<ActivepointList::const_iterator,bool> const_findresult;
+
+
+ private:
+ mutable Node::time_set times;
+ public:
+ ValueNode::RHandle value_node;
+
+ ActivepointList timing_info;
+
+ private:
+ int index;
+ etl::loose_handle<ValueNode> parent_;
+ void set_parent_value_node(const etl::loose_handle<ValueNode> &x) { parent_=x; }
+
+ public:
+
+ int get_index()const { return index; }
+
+
+ bool status_at_time(const Time &x)const;
+
+ float amount_at_time(const Time &x, bool *rising=0)const;
+
+ ActivepointList::iterator add(Time time, bool status, int priority=0);
+ ActivepointList::iterator add(const Activepoint &x);
+
+ findresult find_uid(const UniqueID& x);
+ const_findresult find_uid(const UniqueID& x)const;
+
+ findresult find_time(const Time& x);
+ const_findresult find_time(const Time& x)const;
+
+ ActivepointList::iterator find(const UniqueID& x);
+ ActivepointList::const_iterator find(const UniqueID& x)const;
+ ActivepointList::iterator find(const Time& x);
+ ActivepointList::const_iterator find(const Time& x)const;
+ ActivepointList::iterator find_prev(const Time& x);
+ ActivepointList::const_iterator find_prev(const Time& x)const;
+ ActivepointList::iterator find_next(const Time& x);
+ ActivepointList::const_iterator find_next(const Time& x)const;
+
+ Activepoint new_activepoint_at_time(const Time& x)const;
+
+ ActivepointList::iterator add(Time time)
+ { return add(time, status_at_time(time)); }
+
+ void erase(const UniqueID& x);
+
+ int find(const Time& begin,const Time& end,std::vector<Activepoint*>& list);
+
+ const sinfg::Node::time_set &get_times() const;
+
+ const etl::loose_handle<ValueNode> &get_parent_value_node()const { return parent_; }
+
+ ListEntry();
+ ListEntry(const ValueNode::Handle &value_node);
+ ListEntry(const ValueNode::Handle &value_node,Time begin, Time end);
+ }; // END of struct ValueNode_DynamicList::ListEntry
+
+ typedef etl::handle<ValueNode_DynamicList> Handle;
+ typedef etl::handle<const ValueNode_DynamicList> ConstHandle;
+
+protected:
+ ValueNode_DynamicList(ValueBase::Type container_type=ValueBase::TYPE_NIL);
+
+ ValueBase::Type container_type;
+
+ bool loop_;
+
+
+public:
+ std::vector<ListEntry> list;
+
+public:
+
+ void add(const ValueNode::Handle &value_node, int index=-1);
+ void add(const ListEntry &value_node, int index=-1);
+ void erase(const ValueNode::Handle &value_node);
+ void reindex();
+
+ int find_next_valid_entry(int x, Time t)const;
+ int find_prev_valid_entry(int x, Time t)const;
+
+ virtual ValueNode::LooseHandle get_link_vfunc(int i)const;
+
+ virtual int link_count()const;
+
+ virtual String link_name(int i)const;
+
+ virtual ValueBase operator()(Time t)const;
+
+ virtual ~ValueNode_DynamicList();
+
+ virtual String link_local_name(int i)const;
+ virtual int get_link_index_from_name(const String &name)const;
+
+ virtual String get_name()const;
+ virtual String get_local_name()const;
+
+ bool get_loop()const { return loop_; }
+ void set_loop(bool x) { loop_=x; }
+
+ ValueBase::Type get_contained_type()const;
+
+
+ template <typename iterator> static Handle
+ create(iterator begin, iterator end)
+ {
+ Handle ret=create((*begin)->get_type());
+ for(;begin!=end;++begin)
+ ret->add(ListEntry(*begin));
+ return ret;
+ }
+
+ void insert_time(const Time& location, const Time& delta);
+ //void manipulate_time(const Time& old_begin,const Time& old_end,const Time& new_begin,const Time& new_end);
+
+ virtual ValueNode* clone(const GUID& deriv_guid=GUID())const;
+
+ virtual ListEntry create_list_entry(int index, Time time=0, Real origin=0.5);
+
+protected:
+
+ virtual bool set_link_vfunc(int i,ValueNode::Handle x);
+ LinkableValueNode* create_new()const;
+
+ virtual void get_times_vfunc(Node::time_set &set) const;
+
+public:
+ /*! \note The construction parameter (\a id) is the type that the list
+ ** contains, rather than the type that it will yield
+ ** (which is ValueBase::TYPE_LIST)
+ */
+ static Handle create(ValueBase::Type id=ValueBase::TYPE_NIL);
+ using sinfg::LinkableValueNode::get_link_vfunc;
+ using sinfg::LinkableValueNode::set_link_vfunc;
+ static bool check_type(ValueBase::Type type);
+ static ValueNode_DynamicList* create_from(const ValueBase &x=ValueBase::TYPE_GRADIENT);
+}; // END of class ValueNode_DynamicList
+
+typedef ValueNode_DynamicList::ListEntry::Activepoint Activepoint;
+typedef ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
+
+}; // END of namespace sinfg
+
+/* === E N D =============================================================== */
+
+#endif