Initial Stable Commit
[synfig.git] / synfig-core / trunk / src / modules / mod_geometry / region.cpp
1 /*! ========================================================================
2 ** Sinfg
3 ** Template File
4 ** $Id: region.cpp,v 1.1.1.1 2005/01/04 01:23:10 darco Exp $
5 **
6 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
7 **
8 ** This software and associated documentation
9 ** are CONFIDENTIAL and PROPRIETARY property of
10 ** the above-mentioned copyright holder.
11 **
12 ** You may not copy, print, publish, or in any
13 ** other way distribute this software without
14 ** a prior written agreement with
15 ** the copyright holder.
16 **
17 ** === N O T E S ===========================================================
18 **
19 ** ========================================================================= */
20
21 /* === H E A D E R S ======================================================= */
22
23 #ifdef USING_PCH
24 #       include "pch.h"
25 #else
26 #ifdef HAVE_CONFIG_H
27 #       include <config.h>
28 #endif
29
30 #include "region.h"
31 #include <ETL/stringf>
32 #include <ETL/bezier>
33 #include <ETL/hermite>
34
35 #include <sinfg/string.h>
36 #include <sinfg/time.h>
37 #include <sinfg/context.h>
38 #include <sinfg/paramdesc.h>
39 #include <sinfg/renddesc.h>
40 #include <sinfg/surface.h>
41 #include <sinfg/value.h>
42 #include <sinfg/valuenode.h>
43 #include <sinfg/segment.h>
44 #include <sinfg/valuenode_bline.h>
45
46 #endif
47
48 using namespace etl;
49
50 /* === M A C R O S ========================================================= */
51
52 #define SAMPLES         75
53
54 /* === G L O B A L S ======================================================= */
55
56 SINFG_LAYER_INIT(Region);
57 SINFG_LAYER_SET_NAME(Region,"region");
58 SINFG_LAYER_SET_LOCAL_NAME(Region,_("Region"));
59 SINFG_LAYER_SET_CATEGORY(Region,_("Geometry"));
60 SINFG_LAYER_SET_VERSION(Region,"0.1");
61 SINFG_LAYER_SET_CVS_ID(Region,"$Id: region.cpp,v 1.1.1.1 2005/01/04 01:23:10 darco Exp $");
62
63 /* === P R O C E D U R E S ================================================= */
64
65 /* === M E T H O D S ======================================================= */
66
67 /* === E N T R Y P O I N T ================================================= */
68
69 Region::Region()
70 {
71         clear();
72         vector<BLinePoint> bline_point_list;
73         bline_point_list.push_back(BLinePoint());
74         bline_point_list.push_back(BLinePoint());
75         bline_point_list.push_back(BLinePoint());
76         bline_point_list[0].set_vertex(Point(0,1));     
77         bline_point_list[1].set_vertex(Point(0,-1));    
78         bline_point_list[2].set_vertex(Point(1,0));
79         bline_point_list[0].set_tangent(bline_point_list[1].get_vertex()-bline_point_list[2].get_vertex()*0.5f);        
80         bline_point_list[1].set_tangent(bline_point_list[2].get_vertex()-bline_point_list[0].get_vertex()*0.5f);        
81         bline_point_list[2].set_tangent(bline_point_list[0].get_vertex()-bline_point_list[1].get_vertex()*0.5f);        
82         bline_point_list[0].set_width(1.0f);    
83         bline_point_list[1].set_width(1.0f);    
84         bline_point_list[2].set_width(1.0f);    
85         bline=bline_point_list;
86 }
87
88 void
89 Region::sync()
90 {
91         if(bline.get_contained_type()==ValueBase::TYPE_BLINEPOINT)
92         {
93                 segment_list=convert_bline_to_segment_list(bline);
94         }
95         else
96         {
97                 sinfg::warning("Region: incorrect type on bline, layer disabled");
98                 clear();
99                 return;
100         }
101
102         if(segment_list.empty())
103         {
104                 sinfg::warning("Region: segment_list is empty, layer disabled");
105                 clear();
106                 return;
107         }
108         
109         bool looped = bline.get_loop();
110
111         Vector::value_type n;
112         etl::hermite<Vector> curve;
113         vector<Point> vector_list;
114
115         vector<Segment>::const_iterator iter=segment_list.begin();
116         //Vector                                                        last = iter->p1;
117         
118         //make sure the shape has a clean slate for writing
119         //clear();
120         
121         //and start off at the first point
122         //move_to(last[0],last[1]);
123         
124         for(;iter!=segment_list.end();++iter)
125         {
126                 //connect them with a line if they aren't already joined
127                 /*if(iter->p1 != last)
128                 {
129                         line_to(iter->p1[0],iter->p1[1]);
130                 }
131                 
132                 //curve to the next end point
133                 curve_to(iter->p1[0] + iter->t1[0]/3.0,iter->p1[1] + iter->t1[1]/3.0,
134                                  iter->p2[0] - iter->t2[0]/3.0,iter->p2[1] - iter->t2[1]/3.0,
135                                  iter->p2[0],iter->p2[1]);
136                 
137                 last = iter->p2;*/
138                 
139                 if(iter->t1.is_equal_to(Vector(0,0)) && iter->t2.is_equal_to(Vector(0,0)))
140                 {
141                         vector_list.push_back(iter->p2);
142                 }
143                 else
144                 {
145                         curve.p1()=iter->p1;
146                         curve.t1()=iter->t1;
147                         curve.p2()=iter->p2;
148                         curve.t2()=iter->t2;
149                         curve.sync();
150
151                         for(n=0.0;n<1.0;n+=1.0/SAMPLES)
152                                 vector_list.push_back(curve(n));
153                 }
154         }
155         
156         //add a single point onto the end so it actually fits the shape, so we can be awesome...
157         if(!looped)
158         {
159                 vector_list.push_back(curve.p2());
160         }
161
162         clear();
163         add_polygon(vector_list);
164         
165         /*close();
166         endpath();*/
167 }
168
169 bool
170 Region::set_param(const String & param, const ValueBase &value)
171 {
172         if(param=="segment_list")
173         {
174                 if(dynamic_param_list().count("segment_list"))
175                 {
176                         connect_dynamic_param("bline",dynamic_param_list().find("segment_list")->second);
177                         disconnect_dynamic_param("segment_list");
178                         sinfg::warning("Region::set_param(): Updated valuenode connection to use the new \"bline\" parameter.");
179                 }
180                 else
181                         sinfg::warning("Region::set_param(): The parameter \"segment_list\" is deprecated. Use \"bline\" instead.");
182         }
183         
184         if(     (param=="segment_list" || param=="bline") && value.get_type()==ValueBase::TYPE_LIST)
185         {
186                 //if(value.get_contained_type()!=ValueBase::TYPE_BLINEPOINT)
187                 //      return false;
188                         
189                 bline=value;
190
191                 return true;
192         }
193
194 /*      if(     param=="segment_list" && value.get_type()==ValueBase::TYPE_LIST)
195         {
196                 if(value.get_contained_type()==ValueBase::TYPE_BLINEPOINT)
197                         segment_list=convert_bline_to_segment_list(value);
198                 else
199                 if(value.get_contained_type()==ValueBase::TYPE_SEGMENT)
200                         segment_list=value;
201                 else
202                 if(value.empty())
203                         segment_list.clear();
204                 else
205                         return false;
206                 sync();
207                 return true;
208         }
209         */
210         return Layer_Shape::set_param(param,value);
211 }
212
213 ValueBase
214 Region::get_param(const String& param)const
215 {
216         EXPORT(bline);
217         EXPORT_NAME();
218         EXPORT_VERSION();
219
220         return Layer_Shape::get_param(param);
221 }
222
223 Layer::Vocab
224 Region::get_param_vocab()const
225 {
226         Layer::Vocab ret(Layer_Shape::get_param_vocab());
227
228         ret.push_back(ParamDesc("bline")
229                 .set_local_name(_("Vertices"))
230                 .set_origin("offset")
231         );
232
233         return ret;
234 }
235
236 void
237 Region::set_time(Context context, Time time)const
238 {
239         const_cast<Region*>(this)->sync();
240         context.set_time(time);
241 }
242
243 void
244 Region::set_time(Context context, Time time, Vector pos)const
245 {
246         const_cast<Region*>(this)->sync();
247         context.set_time(time,pos);
248 }