Made a start at implementing the ideas in http://synfig.org/Linking_to_Blines . ...
[synfig.git] / synfig-studio / trunk / src / synfigapp / actions / valuedescblinelink.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file valuedescblinelink.cpp
3 **      \brief Template File
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2007, 2008 Chris Moore
10 **
11 **      This package is free software; you can redistribute it and/or
12 **      modify it under the terms of the GNU General Public License as
13 **      published by the Free Software Foundation; either version 2 of
14 **      the License, or (at your option) any later version.
15 **
16 **      This package is distributed in the hope that it will be useful,
17 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
18 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 **      General Public License for more details.
20 **      \endlegal
21 */
22 /* ========================================================================= */
23
24 /* === H E A D E R S ======================================================= */
25
26 #ifdef USING_PCH
27 #       include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 #       include <config.h>
31 #endif
32
33 #include "valuenodelinkconnect.h"
34 #include "valuedescblinelink.h"
35
36 #include <synfigapp/canvasinterface.h>
37 #include <synfig/valuenode_const.h>
38 #include <synfig/valuenode_composite.h>
39 #include <synfig/valuenode_blinecalcvertex.h>
40
41 #include <synfigapp/general.h>
42
43 #endif
44
45 using namespace std;
46 using namespace etl;
47 using namespace synfig;
48 using namespace synfigapp;
49 using namespace Action;
50
51 /* === M A C R O S ========================================================= */
52
53 ACTION_INIT(Action::ValueDescBLineLink);
54 ACTION_SET_NAME(Action::ValueDescBLineLink,"value_desc_bline_link");
55 ACTION_SET_LOCAL_NAME(Action::ValueDescBLineLink,N_("Link to BLine"));
56 ACTION_SET_TASK(Action::ValueDescBLineLink,"connect");
57 ACTION_SET_CATEGORY(Action::ValueDescBLineLink,Action::CATEGORY_BEZIER);
58 ACTION_SET_PRIORITY(Action::ValueDescBLineLink,0);
59 ACTION_SET_VERSION(Action::ValueDescBLineLink,"0.0");
60 ACTION_SET_CVS_ID(Action::ValueDescBLineLink,"$Id$");
61
62 /* === G L O B A L S ======================================================= */
63
64 /* === P R O C E D U R E S ================================================= */
65
66 /* === M E T H O D S ======================================================= */
67
68 Action::ValueDescBLineLink::ValueDescBLineLink()
69 {
70 }
71
72 Action::ParamVocab
73 Action::ValueDescBLineLink::get_param_vocab()
74 {
75         ParamVocab ret(Action::CanvasSpecific::get_param_vocab());
76
77         ret.push_back(ParamDesc("selected_value_desc",Param::TYPE_VALUEDESC)
78                 .set_local_name(_("ValueDesc to link"))
79                 .set_supports_multiple()
80         );
81         ret.push_back(ParamDesc("value_desc",Param::TYPE_VALUEDESC)
82                 .set_local_name(_("ValueDesc on BLine to link to"))
83         );
84         ret.push_back(ParamDesc("time",Param::TYPE_TIME)
85                 .set_local_name(_("Time"))
86                 .set_optional()
87         );
88         ret.push_back(ParamDesc("origin",Param::TYPE_REAL)
89                 .set_local_name(_("Origin"))
90                 .set_optional()
91         );
92
93         return ret;
94 }
95
96 bool
97 Action::ValueDescBLineLink::is_candidate(const ParamList &x)
98 {
99         ParamList::const_iterator i;
100
101         ValueDesc value_desc(x.find("value_desc")->second.get_value_desc());
102
103         if (!candidate_check(get_param_vocab(),x))
104                 return false;
105
106         return (value_desc.parent_is_value_node() &&
107                         // We need a dynamic list.
108                         ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_parent_value_node()));
109 }
110
111 bool
112 Action::ValueDescBLineLink::set_param(const synfig::String& name, const Action::Param &param)
113 {
114         if(name=="time" && param.get_type()==Param::TYPE_TIME)
115         {
116                 time=param.get_time();
117                 return true;
118         }
119
120         if(name=="value_desc" && param.get_type()==Param::TYPE_VALUEDESC)
121         {
122                 value_desc = param.get_value_desc();
123                 index=value_desc.get_index();
124                 return true;
125         }
126
127         if(name=="selected_value_desc" && param.get_type()==Param::TYPE_VALUEDESC)
128         {
129                 ValueDesc value_desc(param.get_value_desc());
130                 value_desc_list.push_back(value_desc);
131                 return true;
132         }
133
134         if(name=="origin" && param.get_type()==Param::TYPE_REAL)
135         {
136                 origin=param.get_real();
137                 return true;
138         }
139
140         return Action::CanvasSpecific::set_param(name,param);
141 }
142
143 bool
144 Action::ValueDescBLineLink::is_ready()const
145 {
146         if(value_desc_list.size()<1)
147                 return false;
148         if(!value_desc)
149                 return false;
150         return Action::CanvasSpecific::is_ready();
151 }
152
153 void
154 Action::ValueDescBLineLink::prepare()
155 {
156         if(value_desc_list.empty())
157                 throw Error(Error::TYPE_NOTREADY);
158
159         clear();
160
161         ValueNode_DynamicList::Handle bline_value_node(ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_parent_value_node()));
162         bool loop(bline_value_node->get_loop());
163         int loop_adjust(loop ? 0 : -1);
164         const std::vector<ValueBase> bline((*bline_value_node)(time));
165         int size = bline.size();
166         Real amount = (index + origin + loop_adjust) / (size + loop_adjust);
167
168         std::list<ValueDesc>::iterator iter;
169         for(iter=value_desc_list.begin();iter!=value_desc_list.end();++iter)
170         {
171                 ValueDesc& value_desc(*iter);
172                 if (value_desc.parent_is_value_node())
173                 {
174                         ValueNode::Handle value_node(value_desc.get_value_node());
175                         if (value_desc.get_value_type()==ValueBase::TYPE_BLINEPOINT &&
176                                 value_desc.is_value_node() &&
177                                 ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()))
178                         {
179                                 LinkableValueNode::Handle bline_vertex(ValueNode_BLineCalcVertex::create(ValueBase::TYPE_VECTOR));
180                                 bline_vertex->set_link("bline", bline_value_node);
181                                 bline_vertex->set_link("loop", ValueNode_Const::create(loop));
182                                 bline_vertex->set_link("amount", ValueNode_Const::create(amount));
183
184                                 Action::Handle action(ValueNodeLinkConnect::create());
185
186                                 action->set_param("canvas",get_canvas());
187                                 action->set_param("canvas_interface",get_canvas_interface());
188                                 action->set_param("parent_value_node",value_node);
189                                 action->set_param("value_node",ValueNode::Handle(bline_vertex));
190                                 action->set_param("index",0); // index for 'vertex' in 'composite'
191
192                                 assert(action->is_ready());
193                                 if(!action->is_ready())
194                                         throw Error(Error::TYPE_NOTREADY);
195
196                                 add_action_front(action);
197                         }
198                 }
199         }
200 }