When we create a 'Duplicate' layer, automatically have its parameter already converte...
[synfig.git] / synfig-core / trunk / src / synfig / layer_duplicate.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file layer_duplicate.cpp
3 **      \brief Implementation of the "Duplicate" layer
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 "string.h"
34 #include "layer_duplicate.h"
35 #include "time.h"
36 #include "context.h"
37 #include "paramdesc.h"
38 #include "renddesc.h"
39 #include "surface.h"
40 #include "value.h"
41 #include "valuenode.h"
42 #include "canvas.h"
43
44 #endif
45
46 /* === U S I N G =========================================================== */
47
48 using namespace synfig;
49 using namespace etl;
50 using namespace std;
51
52 /* === G L O B A L S ======================================================= */
53
54 SYNFIG_LAYER_INIT(Layer_Duplicate);
55 SYNFIG_LAYER_SET_NAME(Layer_Duplicate,"duplicate");
56 SYNFIG_LAYER_SET_LOCAL_NAME(Layer_Duplicate,N_("Duplicate"));
57 SYNFIG_LAYER_SET_CATEGORY(Layer_Duplicate,N_("Other"));
58 SYNFIG_LAYER_SET_VERSION(Layer_Duplicate,"0.1");
59 SYNFIG_LAYER_SET_CVS_ID(Layer_Duplicate,"$Id$");
60
61 /* === M E M B E R S ======================================================= */
62
63 Layer_Duplicate::Layer_Duplicate():
64         Layer_Composite(1.0,Color::BLEND_COMPOSITE)
65 {
66         LinkableValueNode* index_value_node = ValueNode_Duplicate::create(int(3));
67         connect_dynamic_param("index", index_value_node);
68 }
69
70 bool
71 Layer_Duplicate::set_param(const String &param, const ValueBase &value)
72 {
73         IMPORT(index);
74         return Layer_Composite::set_param(param,value);
75 }
76
77 ValueBase
78 Layer_Duplicate::get_param(const String &param)const
79 {
80         EXPORT(index);
81
82         EXPORT_NAME();
83         EXPORT_VERSION();
84
85         return Layer_Composite::get_param(param);
86 }
87
88 void
89 Layer_Duplicate::set_time(Context context, Time time)const
90 {
91         context.set_time(time);
92         time_cur=time;
93 }
94
95 void
96 Layer_Duplicate::set_time(Context context, Time time, const Point &pos)const
97 {
98         context.set_time(time,pos);
99         time_cur=time;
100 }
101
102 Color
103 Layer_Duplicate::get_color(Context context, const Point &pos)const
104 {
105         return context.get_color(pos);
106 }
107
108 Layer::Vocab
109 Layer_Duplicate::get_param_vocab()const
110 {
111         Layer::Vocab ret;
112         //ret=Layer_Composite::get_param_vocab();
113
114         ret.push_back(ParamDesc("index")
115                 .set_local_name(_("Index"))
116                 .set_description(_("Copy Index"))
117         );
118
119         return ret;
120 }
121
122 bool
123 Layer_Duplicate::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const
124 {
125         if(quality == 10)
126                 return context.accelerated_render(surface,quality,renddesc,cb);
127
128         if(context->empty())
129         {
130                 surface->set_wh(renddesc.get_w(),renddesc.get_h());
131                 surface->clear();
132                 return true;
133         }
134
135         SuperCallback subimagecb;
136         Surface tmp;
137         int i = 0;
138
139         const DynamicParamList &dpl = dynamic_param_list();
140         DynamicParamList::const_iterator iter = dpl.find("index");
141         if (iter == dpl.end())
142                 return context.accelerated_render(surface,quality,renddesc,cb);
143
144         etl::rhandle<ValueNode> param(iter->second);
145         handle<ValueNode_Duplicate>     duplicate_param(handle<ValueNode_Duplicate>::cast_dynamic(param));
146
147         if (!duplicate_param)
148                 return context.accelerated_render(surface,quality,renddesc,cb);
149
150         surface->set_wh(renddesc.get_w(),renddesc.get_h());
151         surface->clear();
152
153         Color::BlendMethod blend_method(get_blend_method());
154         int steps = duplicate_param->count_steps(time_cur);
155
156         duplicate_param->reset_index(time_cur);
157         do
158         {
159                 subimagecb=SuperCallback(cb,i*(5000/steps),(i+1)*(5000/steps),5000);
160                 // \todo can we force a re-evaluation of all the variables without changing the time twice?
161                 context.set_time(time_cur+1);
162                 context.set_time(time_cur);
163                 if(!context.accelerated_render(&tmp,quality,renddesc,&subimagecb)) return false;
164
165                 Surface::alpha_pen apen(surface->begin());
166                 apen.set_alpha(1.0);
167                 // \todo have a checkbox allowing use of 'behind' to reverse the order?
168                 apen.set_blend_method(blend_method);
169                 tmp.blit_to(apen);
170                 i++;
171         } while (duplicate_param->step(time_cur));
172
173         duplicate_param->reset_index(time_cur);
174
175         return true;
176 }