Enable duck reverse manipulation for Range value node convert types.
authorCarlos Lopez <genetita@gmail.com>
Sun, 25 Oct 2009 17:49:07 +0000 (18:49 +0100)
committerCarlos Lopez <genetita@gmail.com>
Sun, 25 Oct 2009 17:49:07 +0000 (18:49 +0100)
synfig-core/src/synfig/valuenode_range.cpp
synfig-core/src/synfig/valuenode_range.h
synfig-studio/src/gtkmm/canvasview.cpp
synfig-studio/src/synfigapp/instance.cpp

index c4107f8..be2f6a2 100644 (file)
@@ -159,6 +159,65 @@ synfig::ValueNode_Range::operator()(Time t)const
        return ValueBase();
 }
 
+synfig::ValueBase
+synfig::ValueNode_Range::get_inverse(Time t, const synfig::Vector &target_value) const
+{
+       switch (get_type())
+       {
+               case ValueBase::TYPE_INTEGER:
+                       {
+                       int max_value((*max_)(t).get(int()));
+                       int min_value((*min_)(t).get(int()));
+                       return std::max(min_value, std::min(max_value, int(target_value.mag())));
+                       }
+               case ValueBase::TYPE_REAL:
+                       {
+                       Real max_value((*max_)(t).get(Real()));
+                       Real min_value((*min_)(t).get(Real()));
+                       return std::max(min_value, std::min(max_value, target_value.mag()));
+                       }
+               case ValueBase::TYPE_ANGLE:
+                       {
+                       Angle max_value((*max_)(t).get(Angle()));
+                       Angle min_value((*min_)(t).get(Angle()));
+                       Angle target_angle(Angle::tan(target_value[1],target_value[0]));
+                       return target_angle>max_value?max_value:target_angle<min_value?min_value:target_angle;
+                       }
+               case ValueBase::TYPE_TIME:
+                       {
+                       Real max_value((*max_)(t).get(Time()));
+                       Real min_value((*min_)(t).get(Time()));
+                       return std::max(min_value, std::min(max_value, target_value.mag()));
+                       }
+               default:
+                       return target_value;
+       }
+       return ValueBase();
+}
+
+synfig::ValueBase
+synfig::ValueNode_Range::get_inverse(Time t, const synfig::Angle &target_value) const
+{
+       Angle minimum = (* min_)(t).get(Angle());
+       Angle maximum = (* max_)(t).get(Angle());
+       Angle link = (*link_)(t).get(Angle());
+               switch (get_type())
+               {
+                       default:
+               // Notice that target_value is the rotation between the current
+               // 'link' value and the target angle in the canvas, so we need
+               // to add it to 'link'
+               if(Angle::rad(maximum).get()>=Angle::rad(link+target_value).get() && Angle::rad(link+target_value).get()>=Angle::rad(minimum).get())
+                       return link + target_value;
+               else if (Angle::rad(minimum).get()>Angle::rad(target_value).get())
+                       return minimum;
+               else
+                       return maximum;
+               }
+       return ValueBase();
+}
+
+
 bool
 ValueNode_Range::set_link_vfunc(int i,ValueNode::Handle value)
 {
index 9fde110..8325820 100644 (file)
@@ -55,6 +55,10 @@ public:
        virtual String get_name()const;
        virtual String get_local_name()const;
 
+       //! Returns the modified Link to match the target value at time t
+       ValueBase get_inverse(Time t, const synfig::Vector &target_value) const;
+       ValueBase get_inverse(Time t, const synfig::Angle &target_value) const;
+
        virtual ValueNode::LooseHandle get_link_vfunc(int i)const;
        virtual int link_count()const;
        virtual String link_name(int i)const;
index 807a63e..5afa535 100644 (file)
@@ -52,6 +52,7 @@
 #include <synfig/valuenode_linear.h>
 #include <synfig/valuenode_timedswap.h>
 #include <synfig/valuenode_scale.h>
+#include <synfig/valuenode_range.h>
 #include <synfig/valuenode_dynamiclist.h>
 #include <synfig/valuenode_twotone.h>
 #include <synfig/valuenode_stripes.h>
@@ -2949,6 +2950,15 @@ CanvasView::on_duck_changed(const synfig::Point &value,const synfigapp::ValueDes
                        return false;
        }
 
+       if (ValueNode_Range::Handle range_value_node = ValueNode_Range::Handle::cast_dynamic(value_desc.get_value_node()))
+       {
+               int link_index(range_value_node->get_link_index_from_name("link"));
+               return canvas_interface()->change_value(
+                       synfigapp::ValueDesc(range_value_node,link_index),
+                               range_value_node->get_inverse(get_time(), value)
+                               );
+       }
+
        switch(value_desc.get_value_type())
        {
        case ValueBase::TYPE_REAL:
@@ -2982,6 +2992,14 @@ CanvasView::on_duck_angle_changed(const synfig::Angle &rotation,const synfigapp:
                        return false;
 
        }
+       if (ValueNode_Range::Handle range_value_node = ValueNode_Range::Handle::cast_dynamic(value_desc.get_value_node()))
+       {
+               int link_index(range_value_node->get_link_index_from_name("link"));
+               return canvas_interface()->change_value(
+                       synfigapp::ValueDesc(range_value_node,link_index),
+                               range_value_node->get_inverse(get_time(), rotation)
+                               );
+       }
        // \todo will this really always be the case?
        assert(value_desc.get_value_type() == ValueBase::TYPE_ANGLE);
        return canvas_interface()->change_value(value_desc, value_desc.get_value(get_time()).get(Angle()) + rotation);
index c3c542b..69dfb84 100644 (file)
@@ -43,6 +43,7 @@
 #include <synfig/valuenode_blinecalcvertex.h>
 #include <synfig/valuenode_blinecalcwidth.h>
 #include <synfig/valuenode_scale.h>
+#include <synfig/valuenode_range.h>
 #include <map>
 
 #include "general.h"
@@ -76,6 +77,7 @@ synfigapp::is_editable(synfig::ValueNode::Handle value_node)
                || ValueNode_BLineCalcTangent::Handle::cast_dynamic(value_node)
                || ValueNode_BLineCalcWidth::Handle::cast_dynamic(value_node)
                || ValueNode_Scale::Handle::cast_dynamic(value_node)
+               || ValueNode_Range::Handle::cast_dynamic(value_node)
        )
                return true;
        return false;