source: synfigstudio/trunk/fuentes/src/synfigapp/actions/valuenodedynamiclistinsertsmart.cpp @ 481

Last change on this file since 481 was 481, checked in by jrpelegrina, 4 years ago

First release to xenial

File size: 15.0 KB
Line 
1/* === S Y N F I G ========================================================= */
2/*!     \file valuenodedynamiclistinsertsmart.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 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 "valuenodedynamiclistinsertsmart.h"
34#include "valuenodedynamiclistinsert.h"
35#include <synfigapp/canvasinterface.h>
36
37#include <synfigapp/general.h>
38
39#endif
40
41using namespace std;
42using namespace etl;
43using namespace synfig;
44using namespace synfigapp;
45using namespace Action;
46
47/* === M A C R O S ========================================================= */
48
49ACTION_INIT(Action::ValueNodeDynamicListInsertSmart);
50ACTION_SET_NAME(Action::ValueNodeDynamicListInsertSmart,"ValueNodeDynamicListInsertSmart");
51ACTION_SET_LOCAL_NAME(Action::ValueNodeDynamicListInsertSmart,N_("Insert Item"));
52ACTION_SET_TASK(Action::ValueNodeDynamicListInsertSmart,"insert");
53ACTION_SET_CATEGORY(Action::ValueNodeDynamicListInsertSmart,Action::CATEGORY_VALUEDESC|Action::CATEGORY_VALUENODE);
54ACTION_SET_PRIORITY(Action::ValueNodeDynamicListInsertSmart,-20);
55ACTION_SET_VERSION(Action::ValueNodeDynamicListInsertSmart,"0.0");
56ACTION_SET_CVS_ID(Action::ValueNodeDynamicListInsertSmart,"$Id$");
57
58ACTION_INIT(Action::ValueNodeDynamicListInsertSmartKeepShape);
59ACTION_SET_NAME(Action::ValueNodeDynamicListInsertSmartKeepShape,"ValueNodeDynamicListInsertSmartKeepShape");
60ACTION_SET_LOCAL_NAME(Action::ValueNodeDynamicListInsertSmartKeepShape,N_("Insert Item & Keep Shape"));
61ACTION_SET_TASK(Action::ValueNodeDynamicListInsertSmartKeepShape,"insert");
62ACTION_SET_CATEGORY(Action::ValueNodeDynamicListInsertSmartKeepShape,Action::CATEGORY_VALUEDESC|Action::CATEGORY_VALUENODE);
63ACTION_SET_PRIORITY(Action::ValueNodeDynamicListInsertSmartKeepShape,-21);
64ACTION_SET_VERSION(Action::ValueNodeDynamicListInsertSmartKeepShape,"0.0");
65ACTION_SET_CVS_ID(Action::ValueNodeDynamicListInsertSmartKeepShape,"$Id$");
66
67/* === G L O B A L S ======================================================= */
68
69/* === P R O C E D U R E S ================================================= */
70
71/* === M E T H O D S ======================================================= */
72///////////// VALUENODEDYNAMICLISTINSERTITEMSMART
73Action::ValueNodeDynamicListInsertSmart::ValueNodeDynamicListInsertSmart() :
74        keep_shape(false)
75{
76        index=0;
77        time=0;
78        origin=0.5f;
79        set_dirty(true);
80}
81
82Action::ParamVocab
83Action::ValueNodeDynamicListInsertSmart::get_param_vocab()
84{
85        ParamVocab ret(Action::CanvasSpecific::get_param_vocab());
86
87        ret.push_back(ParamDesc("value_desc",Param::TYPE_VALUEDESC)
88                .set_local_name(_("ValueDesc"))
89        );
90        ret.push_back(ParamDesc("time",Param::TYPE_TIME)
91                .set_local_name(_("Time"))
92                .set_optional()
93        );
94        ret.push_back(ParamDesc("origin",Param::TYPE_REAL)
95                .set_local_name(_("Origin"))
96                .set_optional()
97        );
98
99        return ret;
100}
101
102bool
103Action::ValueNodeDynamicListInsertSmart::is_candidate(const ParamList &x)
104{
105        if (!candidate_check(get_param_vocab(),x))
106                return false;
107
108        ValueDesc value_desc(x.find("value_desc")->second.get_value_desc());
109
110        return ( (value_desc.parent_is_value_node() &&
111                        // We need a Dynamic List parent.
112                        ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_parent_value_node()))
113                        ||
114                        // Or a Dynamic List value node
115                        (value_desc.is_value_node() &&
116                        ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_value_node())) );
117}
118
119bool
120Action::ValueNodeDynamicListInsertSmart::set_param(const synfig::String& name, const Action::Param &param)
121{
122        if(name=="value_desc" && param.get_type()==Param::TYPE_VALUEDESC)
123        {
124                ValueDesc value_desc(param.get_value_desc());
125
126                if(!value_desc.parent_is_value_node())
127                {
128                        if(value_desc.is_value_node())
129                        {
130                                value_node=ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_value_node());
131                                index=0;
132                        }
133                        else
134                                return false;
135                }
136                else
137                {
138                        value_node=ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_parent_value_node());
139                        index=value_desc.get_index();
140                }
141                if(!value_node)
142                        return false;
143                return true;
144        }
145        if(name=="time" && param.get_type()==Param::TYPE_TIME)
146        {
147                time=param.get_time();
148
149                return true;
150        }
151        if(name=="origin" && param.get_type()==Param::TYPE_REAL)
152        {
153                origin=param.get_real();
154
155                return true;
156        }
157
158        return Action::CanvasSpecific::set_param(name,param);
159}
160
161bool
162Action::ValueNodeDynamicListInsertSmart::is_ready()const
163{
164        if(!value_node)
165                return false;
166        return Action::CanvasSpecific::is_ready();
167}
168
169void
170Action::ValueNodeDynamicListInsertSmart::prepare()
171{
172        //clear();
173        // HACK
174        if(!first_time())
175                return;
176
177        // If we are in animate editing mode
178        if(get_edit_mode()&MODE_ANIMATE)
179        {
180                int index(ValueNodeDynamicListInsertSmart::index);
181
182                // In this case we need to first determine if there is
183                // a currently disabled item in the list that we can
184                // turn on. If not, then we need to go ahead and create one.
185                synfig::info("ValueNodeDynamicListInsertSmart: index=%d",index);
186                synfig::info("ValueNodeDynamicListInsertSmart: value_node->list.size()=%d",value_node->list.size());
187                if(int(value_node->list.size())<=index && index>0)
188                        synfig::info("ValueNodeDynamicListInsertSmart: value_node->list[index-1].status_at_time(time)=%d",value_node->list[index-1].status_at_time(time));
189
190                if(int(value_node->list.size())>=index && index>0 && !value_node->list[index-1].status_at_time(time))
191                {
192                        // Ok, we do not have to create a new
193                        // entry in the dynamic list after all.
194                        // However, we do need to set the
195                        // position and tangent of this point.
196                        ValueNode_DynamicList::ListEntry list_entry(value_node->create_list_entry(index,time,origin));
197                        ValueBase value((*list_entry.value_node)(time));
198                        index--;
199
200                        ValueDesc item_value_desc(value_node,index);
201
202                        Action::Handle action(Action::create("ValueDescSet"));
203
204                        if(!action)
205                                throw Error(_("Unable to find action ValueDescSet (bug)"));
206
207                        action->set_param("edit_mode",get_edit_mode());
208                        action->set_param("canvas",get_canvas());
209                        action->set_param("canvas_interface",get_canvas_interface());
210                        action->set_param("time",time);
211                        action->set_param("new_value",value);
212                        action->set_param("value_desc",ValueDesc(value_node,index));
213
214                        if(!action->is_ready())
215                                throw Error(Error::TYPE_NOTREADY);
216
217                        add_action(action);
218                }
219                else
220                {
221                        // Ok, not a big deal, we just need to
222                        // add a new item
223                        Action::Handle action(Action::create("ValueNodeDynamicListInsert"));
224
225                        if(!action)
226                                throw Error(_("Unable to find action (bug)"));
227
228                        action->set_param("canvas",get_canvas());
229                        action->set_param("canvas_interface",get_canvas_interface());
230                        action->set_param("time",time);
231                        action->set_param("origin",origin);
232                        action->set_param("value_desc",ValueDesc(value_node,index));
233
234                        if(!action->is_ready())
235                                throw Error(Error::TYPE_NOTREADY);
236
237                        add_action(action);
238
239                        // This commented code creates a 'off' Active Point at time.begin()
240                        // that produces bugs like
241                        action=Action::create("ActivepointSetOff");
242
243                        if(!action)
244                                throw Error(_("Unable to find action \"ActivepointSetOff\""));
245
246                        action->set_param("edit_mode",MODE_ANIMATE);
247                        action->set_param("canvas",get_canvas());
248                        action->set_param("canvas_interface",get_canvas_interface());
249                        action->set_param("time",Time::begin());
250                        action->set_param("origin",origin);
251                        action->set_param("value_desc",ValueDesc(value_node,index));
252
253                        if(!action->is_ready())
254                                throw Error(Error::TYPE_NOTREADY);
255
256                        add_action(action);
257                        // If we are inserting the first element, or don't want to
258                        // keep the shape, there is nothing more to do
259                        if(value_node->list.size() > 0 && keep_shape)
260                        {
261                                // If we are inserting on a BLine,
262                                // once we add a new item, we need to update the tangent's radius
263                                // of the previous and next entries from the index to keep the
264                                // shape of the curve
265                                if(value_node->get_contained_type() == type_bline_point)
266                                {
267                                        int prev, next, after, before;
268                                        if(!value_node->list[index].status_at_time(time))
269                                                next=value_node->find_next_valid_entry(index,time);
270                                        else
271                                                next=index;
272                                        after=next+1;
273                                        prev=value_node->find_prev_valid_entry(index,time);
274                                        before=prev;
275                                        if(next==0)
276                                                before++;
277                                        assert(prev>=0);
278                                        assert(next>=0);
279                                        ValueNode_DynamicList::ListEntry next_list_entry(value_node->list[next]);
280                                        ValueNode_DynamicList::ListEntry prev_list_entry(value_node->list[prev]);
281                                        BLinePoint bpn((*next_list_entry.value_node)(time).get(synfig::BLinePoint()));
282                                        BLinePoint bpp((*prev_list_entry.value_node)(time).get(synfig::BLinePoint()));
283                                        // Update previous BLinePoint's tangent's radius
284                                        // Do not add new way-points to the split radius if already split
285                                        if(!bpp.get_split_tangent_radius())
286                                                bpp.set_split_tangent_radius();
287                                        bpp.set_tangent2(Vector(bpp.get_tangent2().mag()*origin, bpp.get_tangent2().angle()));
288                                        // Update next BLinePoint's tangent's radius
289                                        // Do not add new way-points to the split radius if already split
290                                        if(!bpn.get_split_tangent_radius())
291                                                bpn.set_split_tangent_radius();
292                                        bpn.set_tangent1(Vector(bpn.get_tangent1().mag()*(1.0-origin), bpn.get_tangent1().angle()));
293                                        // Now add the actions to modify the value descs
294                                        {
295                                                // BEFORE
296                                                Action::Handle action(Action::create("ValueDescSet"));
297                                                if(!action)
298                                                        throw Error(_("Unable to find action ValueDescSet (bug)"));
299                                                action->set_param("edit_mode",get_edit_mode());
300                                                action->set_param("canvas",get_canvas());
301                                                action->set_param("canvas_interface",get_canvas_interface());
302                                                action->set_param("time",time);
303                                                action->set_param("new_value",ValueBase(bpp));
304                                                action->set_param("value_desc",ValueDesc(value_node,before));
305                                                if(!action->is_ready())
306                                                        throw Error(Error::TYPE_NOTREADY);
307                                                add_action(action);
308                                        }
309                                        {
310                                                // AFTER
311                                                Action::Handle action(Action::create("ValueDescSet"));
312                                                if(!action)
313                                                        throw Error(_("Unable to find action ValueDescSet (bug)"));
314                                                action->set_param("edit_mode",get_edit_mode());
315                                                action->set_param("canvas",get_canvas());
316                                                action->set_param("canvas_interface",get_canvas_interface());
317                                                action->set_param("time",time);
318                                                action->set_param("new_value",ValueBase(bpn));
319                                                action->set_param("value_desc",ValueDesc(value_node,after));
320                                                if(!action->is_ready())
321                                                        throw Error(Error::TYPE_NOTREADY);
322                                                add_action(action);
323                                        }
324                                }
325                        }
326                }
327
328                // Now we set the activepoint up and then we'll be done
329                Action::Handle action(Action::create("ActivepointSetOn"));
330
331                if(!action)
332                        throw Error(_("Unable to find action \"ActivepointSetOn\""));
333
334                action->set_param("edit_mode",get_edit_mode());
335                action->set_param("canvas",get_canvas());
336                action->set_param("canvas_interface",get_canvas_interface());
337                action->set_param("time",time);
338                action->set_param("origin",origin);
339                action->set_param("value_desc",ValueDesc(value_node,index));
340
341                if(!action->is_ready())
342                        throw Error(Error::TYPE_NOTREADY);
343
344                add_action(action);
345        }
346        else
347        {
348                Action::Handle action(Action::create("ValueNodeDynamicListInsert"));
349
350                if(!action)
351                        throw Error(_("Unable to find action (bug)"));
352
353                action->set_param("canvas",get_canvas());
354                action->set_param("canvas_interface",get_canvas_interface());
355                action->set_param("time",time);
356                action->set_param("origin",origin);
357                action->set_param("value_desc",ValueDesc(value_node,index));
358
359                if(!action->is_ready())
360                        throw Error(Error::TYPE_NOTREADY);
361
362                add_action(action);
363                // If we are inserting the first element, or don't want to
364                // keep the shape, there is nothing more to do
365                if(value_node->list.size() > 0 && keep_shape)
366                {
367                        // If we are inserting on a BLine,
368                        // once we add a new item, we need to update the tangent's radius
369                        // of the previous and next entries from the index to keep the
370                        // shape of the curve
371                        if(value_node->get_contained_type() == type_bline_point)
372                        {
373                                int prev, next, after, before;
374                                if(!value_node->list[index].status_at_time(time))
375                                next=value_node->find_next_valid_entry(index,time);
376                                else
377                                        next=index;
378                                after=next+1;
379                                prev=value_node->find_prev_valid_entry(index,time);
380                                before=prev;
381                                if(next==0)
382                                        before++;
383                                assert(prev>=0);
384                                assert(next>=0);
385                                ValueNode_DynamicList::ListEntry next_list_entry(value_node->list[next]);
386                                ValueNode_DynamicList::ListEntry prev_list_entry(value_node->list[prev]);
387                                BLinePoint bpn((*next_list_entry.value_node)(time).get(synfig::BLinePoint()));
388                                BLinePoint bpp((*prev_list_entry.value_node)(time).get(synfig::BLinePoint()));
389                                // Update previous BLinePoint's tangent's radius
390                                // Do not add new way-points to the split radius if already split
391                                if(!bpp.get_split_tangent_radius())
392                                        bpp.set_split_tangent_radius();
393                                bpp.set_tangent2(Vector(bpp.get_tangent2().mag()*origin, bpp.get_tangent2().angle()));
394                                // Update next BLinePoint's tangent's radius
395                                // Do not add new way-points to the split radius if already split
396                                if(!bpn.get_split_tangent_radius())
397                                        bpn.set_split_tangent_radius();
398                                bpn.set_tangent1(Vector(bpn.get_tangent1().mag()*(1.0-origin), bpn.get_tangent1().angle()));
399                                // Now add the actions to modify the value descs
400                                {
401                                        // BEFORE
402                                        Action::Handle action(Action::create("ValueDescSet"));
403                                        if(!action)
404                                                throw Error(_("Unable to find action ValueDescSet (bug)"));
405                                        action->set_param("edit_mode",get_edit_mode());
406                                        action->set_param("canvas",get_canvas());
407                                        action->set_param("canvas_interface",get_canvas_interface());
408                                        action->set_param("time",time);
409                                        action->set_param("new_value",ValueBase(bpp));
410                                        action->set_param("value_desc",ValueDesc(value_node,before));
411                                        if(!action->is_ready())
412                                                throw Error(Error::TYPE_NOTREADY);
413                                        add_action(action);
414                                }
415                                {
416                                        // AFTER
417                                        Action::Handle action(Action::create("ValueDescSet"));
418                                        if(!action)
419                                                throw Error(_("Unable to find action ValueDescSet (bug)"));
420                                        action->set_param("edit_mode",get_edit_mode());
421                                        action->set_param("canvas",get_canvas());
422                                        action->set_param("canvas_interface",get_canvas_interface());
423                                        action->set_param("time",time);
424                                        action->set_param("new_value",ValueBase(bpn));
425                                        action->set_param("value_desc",ValueDesc(value_node,after));
426                                        if(!action->is_ready())
427                                                throw Error(Error::TYPE_NOTREADY);
428                                        add_action(action);
429                                }
430                        }
431                }
432        }
433}
434
435///////////// VALUENODEDYNAMICLISTINSERTITEMSMARTKEEPSHAPE
436Action::ValueNodeDynamicListInsertSmartKeepShape::ValueNodeDynamicListInsertSmartKeepShape()
437{
438        keep_shape=true;
439}
Note: See TracBrowser for help on using the repository browser.