You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

370 lines
8.6KB

  1. /* SpiralPlugin
  2. * Copyleft (C) 2000 David Griffiths <dave@pawfal.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include <stdio.h>
  19. #include "ComplexEnvelopePluginGUI.h"
  20. #include <FL/fl_draw.h>
  21. #include <FL/fl_draw.H>
  22. static const int GUI_COLOUR = 179;
  23. static const int GUIBG_COLOUR = 144;
  24. static const int GUIBG2_COLOUR = 145;
  25. static const float TIMED_SLIDER_MAX = 3.0f;
  26. /////////////////////////////////////////////////////////////////////////
  27. Fl_Envelope::Fl_Handle::Fl_Handle(int x,int y, int w, int h, char *Name) :
  28. Fl_Widget(x,y,w,h,Name),
  29. m_DelMe(false),
  30. m_Changed(false),
  31. m_Coincident(false)
  32. {
  33. }
  34. Fl_Envelope::Fl_Handle::~Fl_Handle()
  35. {
  36. }
  37. int Fl_Envelope::Fl_Handle::handle(int event)
  38. {
  39. int Mousebutton=Fl::event_button();
  40. if (event==FL_DRAG && Mousebutton==1)
  41. {
  42. x(Fl::event_x()-(w()/2));
  43. y(Fl::event_y()-(h()/2));
  44. // restrict the movement to the parent's area
  45. if (x()<parent()->x()) x(parent()->x());
  46. if (x()>parent()->x()+parent()->w()-w()) x(parent()->x()+parent()->w()-w());
  47. if (y()<parent()->y()) y(parent()->y());
  48. if (y()>parent()->y()+parent()->h()-h()) y(parent()->y()+parent()->h()-h());
  49. m_Changed=true;
  50. parent()->redraw();
  51. redraw();
  52. }
  53. if (event==FL_PUSH && Mousebutton==3)
  54. {
  55. m_DelMe=true;
  56. }
  57. return 1;
  58. }
  59. void Fl_Envelope::Fl_Handle::draw()
  60. {
  61. if (m_Coincident)
  62. {
  63. fl_color(FL_BLACK);
  64. fl_rect(x(),y(),w()+1,h()+1);
  65. fl_line(x(),y(),x()+w(),y()+h());
  66. fl_line(x(),y()+h(),x()+w(),y());
  67. }
  68. else
  69. {
  70. fl_color(FL_RED);
  71. fl_arc( x(),y(),w()+1,h()+1,0,360);
  72. }
  73. }
  74. Fl_Envelope::Fl_Envelope(int x,int y, int w, int h, char *Name) :
  75. Fl_Group(x,y,w,h,Name),
  76. m_Length(1.0),
  77. m_Bezier(true)
  78. {
  79. m_Origin_x=x+10;
  80. m_Origin_y=y+h-10;
  81. // default setting
  82. Fl_Handle * newhandle = new Fl_Handle(28,20,10,10,"");
  83. m_HandleList.push_back(newhandle);
  84. add(newhandle);
  85. newhandle = new Fl_Handle(14,122,10,10,"");
  86. m_HandleList.push_back(newhandle);
  87. add(newhandle);
  88. newhandle = new Fl_Handle(48,63,10,10,"");
  89. m_HandleList.push_back(newhandle);
  90. add(newhandle);
  91. newhandle = new Fl_Handle(76,91,10,10,"");
  92. m_HandleList.push_back(newhandle);
  93. add(newhandle);
  94. newhandle = new Fl_Handle(131,86,10,10,"");
  95. m_HandleList.push_back(newhandle);
  96. add(newhandle);
  97. newhandle = new Fl_Handle(194,81,10,10,"");
  98. m_HandleList.push_back(newhandle);
  99. add(newhandle);
  100. newhandle = new Fl_Handle(294,131,10,10,"");
  101. m_HandleList.push_back(newhandle);
  102. add(newhandle);
  103. newhandle = new Fl_Handle(216,124 ,10,10,"");
  104. m_HandleList.push_back(newhandle);
  105. add(newhandle);
  106. show();
  107. }
  108. Fl_Envelope::~Fl_Envelope()
  109. {
  110. end();
  111. }
  112. int Fl_Envelope::handle(int event)
  113. {
  114. int ret=Fl_Group::handle(event);
  115. // search for deleted handles
  116. for(list<Fl_Handle*>::iterator i = m_HandleList.begin();
  117. i!=m_HandleList.end(); ++i)
  118. {
  119. // if it's been modified, update the env via the callback
  120. if ((*i)->Changed()) do_callback();
  121. if ((*i)->Deleted())
  122. {
  123. remove(*i);
  124. m_HandleList.erase(i);
  125. break; // one at a time
  126. }
  127. }
  128. if (!ret)
  129. {
  130. int Mousebutton=Fl::event_button();
  131. if (event==FL_PUSH && Mousebutton==2)
  132. {
  133. Fl_Handle * newhandle = new
  134. Fl_Handle(Fl::event_x()-5,Fl::event_y()-5,10,10,"");
  135. m_HandleList.push_back(newhandle);
  136. add(newhandle);
  137. }
  138. redraw();
  139. }
  140. return ret;
  141. }
  142. void Fl_Envelope::draw()
  143. {
  144. fl_push_clip(x(),y(),w()+1,h()+1);
  145. fl_color(FL_GRAY);
  146. fl_rectf(x(),y(),w()+1,h()+1);
  147. fl_color(FL_BLACK);
  148. fl_rect(x(),y(),w()+1,h()+1);
  149. fl_color(FL_WHITE);
  150. int last_x=m_Origin_x, last_y=m_Origin_y, closest=INT_MAX, dist;
  151. list<Fl_Handle*>::iterator ClosestHandle=m_HandleList.end();
  152. // draw second markers
  153. fl_color(150,150,150);
  154. for (int n=0; n<5; n++)
  155. {
  156. int p=(int)(m_Origin_x+(w()/m_Length*n));
  157. fl_line(p,y(),p,y()+h());
  158. }
  159. m_HandlePos.clear();
  160. m_HandlePos.push_back(Vec2(m_Origin_x,m_Origin_y));
  161. if (m_Bezier) AddToSpline(Vec2(m_Origin_x,m_Origin_y));
  162. for (unsigned int n=0; n<m_HandleList.size(); n++)
  163. {
  164. // slow - search through drawing line connecting handles from left to right
  165. for(list<Fl_Handle*>::iterator i = m_HandleList.begin();
  166. i!=m_HandleList.end(); ++i)
  167. {
  168. dist=(*i)->x()-last_x;
  169. if (dist>-5 && dist<closest)
  170. {
  171. closest=dist;
  172. ClosestHandle=i;
  173. }
  174. }
  175. if (ClosestHandle!=m_HandleList.end())
  176. {
  177. closest=INT_MAX;
  178. fl_color(FL_WHITE);
  179. fl_line(last_x,last_y,(*ClosestHandle)->x()+5,(*ClosestHandle)->y()+5);
  180. (*ClosestHandle)->SetIsCoincident(false);
  181. last_x=(*ClosestHandle)->x()+5;
  182. last_y=(*ClosestHandle)->y()+5;
  183. m_HandlePos.push_back(Vec2((*ClosestHandle)->x()+5,(*ClosestHandle)->y()+5));
  184. if (m_Bezier)
  185. {
  186. if (!(n%3)) (*ClosestHandle)->SetIsCoincident(true);
  187. AddToSpline(Vec2((*ClosestHandle)->x()+5,(*ClosestHandle)->y()+5));
  188. }
  189. }
  190. }
  191. if (m_Bezier)
  192. {
  193. vector<Vec2> BezierLineList;
  194. CalculateBezierSpline(&BezierLineList,10);
  195. vector<Vec2>::iterator bi=BezierLineList.begin();
  196. bi++;
  197. fl_color(FL_BLUE);
  198. for (;bi!=BezierLineList.end(); bi++)
  199. {
  200. fl_line((int)(bi-1)->x,(int)(bi-1)->y,(int)bi->x,(int)bi->y);
  201. }
  202. }
  203. fl_color(FL_BLACK);
  204. fl_line(m_Origin_x,m_Origin_y,m_Origin_x,y()+10);
  205. fl_line(m_Origin_x,m_Origin_y,x()+w()-10,m_Origin_y);
  206. Fl_Group::draw();
  207. fl_pop_clip();
  208. }
  209. void Fl_Envelope::Clear()
  210. {
  211. for(list<Fl_Handle*>::iterator i = m_HandleList.begin();
  212. i!=m_HandleList.end(); ++i)
  213. {
  214. remove(*i);
  215. }
  216. m_HandleList.clear();
  217. }
  218. vector<Vec2> Fl_Envelope::GetCVList()
  219. {
  220. vector<Vec2> m_CV;
  221. for(vector<Vec2>::iterator i = m_HandlePos.begin();
  222. i!=m_HandlePos.end(); ++i)
  223. {
  224. // convert to 0->1
  225. Vec2 vec((i->x-m_Origin_x)/(float)(w()-m_Origin_x),
  226. (m_Origin_y-i->y)/(float)(m_Origin_y-y()));
  227. m_CV.push_back(vec);
  228. }
  229. return m_CV;
  230. }
  231. void Fl_Envelope::SetCVList(const vector<Vec2> &CV)
  232. {
  233. Clear();
  234. for(vector<Vec2>::const_iterator i = CV.begin();
  235. i!=CV.end(); ++i)
  236. {
  237. int minx=m_Origin_x, width=w()-m_Origin_x;
  238. int miny=m_Origin_y, height=m_Origin_y-y();
  239. // convert from 0->1 screen coords
  240. Vec2 vec(minx+(i->x*width),
  241. miny-(i->y*height));
  242. Fl_Handle *nh = new Fl_Handle((int)vec.x,(int)vec.y,10,10,"");
  243. add(nh);
  244. m_HandleList.push_back(nh);
  245. }
  246. redraw();
  247. }
  248. /////////////////////////////////////////////////////////////////////////
  249. ComplexEnvelopePluginGUI::ComplexEnvelopePluginGUI(int w, int h,ComplexEnvelopePlugin *o,const HostInfo *Info) :
  250. SpiralPluginGUI(w,h,o)
  251. {
  252. m_Plugin=o;
  253. m_Type = new Fl_Button(15,h-35,100,20,"Bezier Curve");
  254. m_Type->type(1);
  255. m_Type->value(1);
  256. m_Type->labelsize(10);
  257. m_Type->callback((Fl_Callback*)cb_Type);
  258. m_Length = new Fl_Knob(w-60,h-55,40,40,"Length");
  259. m_Length->color(GUI_COLOUR);
  260. m_Length->labelsize(10);
  261. m_Length->maximum(5);
  262. m_Length->step(0.001);
  263. m_Length->value(1);
  264. m_Length->callback((Fl_Callback*)cb_Length);
  265. m_TLength = new Fl_Output(w-130,h-45,60,20,"");
  266. m_TLength->value("1.0");
  267. m_Envelope = new Fl_Envelope(5,20,w-10,h-75,"");
  268. m_Envelope->callback((Fl_Callback*)cb_UpdateEnv);
  269. end();
  270. }
  271. void ComplexEnvelopePluginGUI::UpdateValues()
  272. {
  273. }
  274. inline void ComplexEnvelopePluginGUI::cb_UpdateEnv_i(Fl_Envelope *o, void* v)
  275. {
  276. m_Plugin->CVListToEnvelope(o->GetCVList());
  277. }
  278. void ComplexEnvelopePluginGUI::cb_UpdateEnv(Fl_Envelope* o, void* v)
  279. {((ComplexEnvelopePluginGUI*)(o->parent()))->cb_UpdateEnv_i(o,v);}
  280. inline void ComplexEnvelopePluginGUI::cb_Type_i(Fl_Button *o, void *v)
  281. {
  282. m_Envelope->SetBezier(o->value());
  283. m_Plugin->SetBezier(o->value());
  284. m_Envelope->redraw();
  285. }
  286. void ComplexEnvelopePluginGUI::cb_Type(Fl_Button *o, void *v)
  287. {((ComplexEnvelopePluginGUI*)(o->parent()))->cb_Type_i(o,v);}
  288. inline void ComplexEnvelopePluginGUI::cb_Length_i(Fl_Knob *o, void *v)
  289. {
  290. m_Plugin->SetLength(o->value());
  291. m_Envelope->SetLength(o->value());
  292. static char text[16];
  293. sprintf(text,"%f",o->value());
  294. m_TLength->value(text);
  295. m_Envelope->redraw();
  296. }
  297. void ComplexEnvelopePluginGUI::cb_Length(Fl_Knob *o, void *v)
  298. {((ComplexEnvelopePluginGUI*)(o->parent()))->cb_Length_i(o,v);}