apply sge motion plugin mods
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / motion / motionwindow.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2012 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "bcdisplayinfo.h"
23 #include "clip.h"
24 #include "edl.h"
25 #include "fonts.h"
26 #include "edlsession.h"
27 #include "language.h"
28 #include "motion.h"
29 #include "motionscan.h"
30 #include "motionwindow.h"
31 #include "mwindow.h"
32 #include "pluginserver.h"
33
34 MotionWindow::MotionWindow(MotionMain *plugin)
35  : PluginClientWindow(plugin, xS(800), yS(750), xS(800), yS(750), 0)
36 {
37         this->plugin = plugin;
38 }
39
40 MotionWindow::~MotionWindow()
41 {
42 }
43
44 void MotionWindow::create_objects()
45 {
46         int xs10 = xS(10), xs20 = xS(20), xs50 = xS(50), xs120 = xS(120);
47         int ys10 = yS(10), ys20 = yS(20), ys50 = yS(50), ys30 = yS(30), ys40 = yS(40);
48         int x = xs10, y = ys10;
49         int x2 = get_w() / 2;
50         BC_Title *title;
51
52         add_subwindow(global = new MotionGlobal(plugin, this, x, y));
53         add_subwindow(rotate = new MotionRotate(plugin, this, x2, y));
54         y += ys50;
55
56         add_subwindow(title = new BC_Title(x, y,
57                 _("Translation search radius:\n(W/H Percent of image)")));
58         add_subwindow(global_range_w = new GlobalRange(plugin,
59                 x + title->get_w() + xs10, y,
60                 &plugin->config.global_range_w));
61         add_subwindow(global_range_h = new GlobalRange(plugin,
62                 x + title->get_w() + xs10 + global_range_w->get_w(), y,
63                 &plugin->config.global_range_h));
64
65         add_subwindow(title = new BC_Title(x2, y,
66                 _("Rotation search radius:\n(Degrees)")));
67         add_subwindow(rotation_range = new RotationRange(plugin,
68                 x2 + title->get_w() + xs10, y));
69
70         y += ys50;
71         add_subwindow(title = new BC_Title(x, y,
72                 _("Translation block size:\n(W/H Percent of image)")));
73         add_subwindow(global_block_w =
74                 new BlockSize(plugin, x + title->get_w() + xs10, y,
75                 &plugin->config.global_block_w));
76         add_subwindow(global_block_h =
77                 new BlockSize(plugin, x + title->get_w() + xs10 +
78                         global_block_w->get_w(), y,
79                         &plugin->config.global_block_h));
80
81 //      add_subwindow(title = new BC_Title(x2,
82 //              y,
83 //              _("Rotation block size:\n(W/H Percent of image)")));
84 //      add_subwindow(rotation_block_w = new BlockSize(plugin,
85 //              x2 + title->get_w() + xs10,
86 //              y,
87 //              &plugin->config.rotation_block_w));
88 //      add_subwindow(rotation_block_h = new BlockSize(plugin,
89 //              x2 + title->get_w() + xs10 + rotation_block_w->get_w(),
90 //              y,
91 //              &plugin->config.rotation_block_h));
92
93         y += ys50;
94         add_subwindow(title = new BC_Title(x, y, _("Translation search steps:")));
95         add_subwindow(global_search_positions =
96                 new GlobalSearchPositions(plugin, x + title->get_w() + xs10, y, xs120));
97         global_search_positions->create_objects();
98
99         add_subwindow(title = new BC_Title(x2, y, _("Rotation search steps:")));
100         add_subwindow(rotation_search_positions =
101                 new RotationSearchPositions(plugin, x2 + title->get_w() + xs10, y, xs120));
102         rotation_search_positions->create_objects();
103
104         y += ys50;
105         add_subwindow(title = new BC_Title(x, y, _("Translation direction:")));
106         add_subwindow(track_direction = new TrackDirection(plugin,
107                 this,
108                 x + title->get_w() + xs10,
109                 y));
110         track_direction->create_objects();
111
112         y += ys40;
113         add_subwindow(title = new BC_Title(x, y + ys10, _("Block X:")));
114         add_subwindow(block_x =
115                 new MotionBlockX(plugin, this, x + title->get_w() + xs10, y));
116         add_subwindow(block_x_text =
117                 new MotionBlockXText(plugin, this,
118                         x + title->get_w() + xs10 + block_x->get_w() + xs10, y + ys10));
119
120         add_subwindow(title = new BC_Title(x2, y + ys10, _("Rotation center:")));
121         add_subwindow(rotation_center =
122                 new RotationCenter(plugin, x2 + title->get_w() + xs10, y));
123
124         y += ys40;
125         add_subwindow(title = new BC_Title(x, y + ys10, _("Block Y:")));
126         add_subwindow(block_y =
127                 new MotionBlockY(plugin, this, x + title->get_w() + xs10, y));
128         add_subwindow(block_y_text =
129                 new MotionBlockYText(plugin, this,
130                         x + title->get_w() + xs10 + block_y->get_w() + xs10, y + ys10));
131
132         y += ys50;
133         add_subwindow(title = new BC_Title(x, y + ys10, _("Maximum absolute offset:")));
134         add_subwindow(magnitude = new MotionMagnitude(plugin,
135                 x + title->get_w() + xs10,
136                 y));
137
138         add_subwindow(title = new BC_Title(x2, y + ys10, _("Maximum angle offset:")));
139         add_subwindow(rotate_magnitude =
140                 new MotionRMagnitude(plugin, x2 + title->get_w() + xs10, y));
141
142         y += ys40;
143         add_subwindow(title = new BC_Title(x, y + ys10, _("Motion settling speed:")));
144         add_subwindow(return_speed =
145                 new MotionReturnSpeed(plugin, x + title->get_w() + xs10, y));
146
147         add_subwindow(title = new BC_Title(x2, y + ys10, _("Rotation settling speed:")));
148         add_subwindow(rotate_return_speed =
149                 new MotionRReturnSpeed(plugin, x2 + title->get_w() + xs10, y));
150
151         y += ys40;
152         add_subwindow(title = new BC_Title(x, y, _("Motion noise level:\n(% of max diff.)")));
153         add_subwindow(noise_level =
154                 new MotionNoiseLevel(plugin, this, x + title->get_w() + xs10, y));
155         add_subwindow(noise_level_text =
156                 new MotionNoiseLevelText(plugin, this,
157                         x + title->get_w() + xs10 + noise_level->get_w() + xs10,        y + ys10));
158
159         add_subwindow(title = new BC_Title(x2, y, _("Rotation noise level:\n(% of max diff.)")));
160         add_subwindow(noise_rotation =
161                 new MotionNoiseRotation(plugin, this, x2 + title->get_w() + xs10, y));
162         add_subwindow(noise_rotation_text =
163                 new MotionNoiseRotationText(plugin, this,
164                         x2 + title->get_w() + xs10 + noise_rotation->get_w() + xs10, y + ys10));
165
166         y += ys50;
167         add_subwindow(vectors = new MotionDrawVectors(plugin, this, x, y));
168         add_subwindow(twopass = new MotionTwopass(plugin, this, x2, y));
169
170         y += ys40;
171         add_subwindow(track_single =
172                 new TrackSingleFrame(plugin, this, x, y));
173
174         add_subwindow(title = new BC_Title(x2, y, _("Frame number:")));
175         add_subwindow(track_frame_number =
176                 new TrackFrameNumber(plugin, this, x2 + title->get_w() + xs10, y));
177         add_subwindow(frame_current =
178                 new MotionFrameCurrent(plugin, this, x2 + title->get_w() + track_frame_number->get_w() + xs20, y));
179         if(plugin->config.tracking_object != MotionScan::TRACK_SINGLE)
180         {
181                 track_frame_number->disable();
182                 frame_current->disable();
183         }
184
185         y += ys20;
186         add_subwindow(track_previous =
187                 new TrackPreviousFrame(plugin, this, x, y));
188
189         y += ys20;
190         add_subwindow(previous_same =
191                 new PreviousFrameSameBlock(plugin, this, x, y));
192
193         add_subwindow(addtrackedframeoffset =
194                 new AddTrackedFrameOffset(plugin, this, x2, y));
195
196         y += ys40;
197         add_subwindow(title = new BC_Title(x, y, _("Tracking file:")));
198         add_subwindow(tracking_file = new MotionTrackingFile(plugin,
199                 plugin->config.tracking_file, this, x+title->get_w() + xs10, y));
200
201         add_subwindow(reset_tracking =
202                 new MotionResetTracking(plugin, this, x2, y));
203
204         y += ys40;
205         add_subwindow(title = new BC_Title(x, y, _("Master layer:")));
206         add_subwindow(master_layer = new MasterLayer(plugin,
207                 this, x + title->get_w() + xs10, y));
208         master_layer->create_objects();
209
210         add_subwindow(clear_tracking =
211                 new MotionClearTracking(plugin, this, x2, y - ys10));
212
213         y += ys30;
214         add_subwindow(title = new BC_Title(x, y, _("Action:")));
215         add_subwindow(action_type = new ActionType(plugin,
216                 this, x + title->get_w() + xs10, y));
217         action_type->create_objects();
218
219         int pef = client->server->mwindow->edl->session->video_every_frame;
220         add_subwindow(pef_title = new BC_Title(x2+xs50, y,
221                 !pef ?  _("For best results\n"
222                                 " Set: Play every frame\n"
223                                 " Preferences-> Playback-> Video Out") :
224                         _("Currently using: Play every frame"), MEDIUMFONT,
225                 !pef ? RED : GREEN));
226
227         y += ys30;
228         add_subwindow(title = new BC_Title(x, y, _("Calculation:")));
229         add_subwindow(tracking_type = new TrackingType(plugin,
230                 this, x + title->get_w() + xs10, y));
231         tracking_type->create_objects();
232
233         show_window(1);
234 }
235
236 void MotionWindow::update_mode()
237 {
238         global_range_w->update(plugin->config.global_range_w,
239                 MIN_RADIUS, MAX_RADIUS);
240         global_range_h->update(plugin->config.global_range_h,
241                 MIN_RADIUS, MAX_RADIUS);
242         rotation_range->update(plugin->config.rotation_range,
243                 MIN_ROTATION, MAX_ROTATION);
244         vectors->update(plugin->config.draw_vectors);
245         twopass->update(plugin->config.twopass);
246         tracking_file->update(plugin->config.tracking_file);
247         global->update(plugin->config.global);
248         rotate->update(plugin->config.rotate);
249         addtrackedframeoffset->update(plugin->config.addtrackedframeoffset);
250 }
251
252 MotionTrackingFile::MotionTrackingFile(MotionMain *plugin,
253         const char *filename, MotionWindow *gui, int x, int y)
254  : BC_TextBox(x, y, gui->get_w()/2-x-xS(10), 1, filename)
255 {
256         this->plugin = plugin;
257         this->gui = gui;
258 };
259
260 int MotionTrackingFile::handle_event()
261 {
262         strncpy(plugin->config.tracking_file, get_text(), sizeof(plugin->config.tracking_file));
263         plugin->reset_cache_file();
264         plugin->send_configure_change();
265         return 1;
266 }
267
268 MotionResetTracking::MotionResetTracking(MotionMain *plugin, MotionWindow *gui, int x, int y)
269  : BC_GenericButton(x, y, _("Generate tracking file name"))
270 {
271         this->plugin = plugin;
272         this->gui = gui;
273 };
274
275 int MotionResetTracking::handle_event()
276 {
277 // First of all, ensure closing current tracking file
278         plugin->reset_cache_file();
279
280 // Generate new tracking filename based on the asset filename
281         const char *sp = TRACKING_FILE;
282         char *cp = plugin->config.tracking_file, *ep = cp+sizeof(plugin->config.tracking_file)-1;
283         while( cp < ep && *sp != 0 ) *cp++ = *sp++;
284         if( cp < ep-1 && (sp=plugin->get_source_path()) ) {
285                 *cp++ = '-';
286                 const char *bp = strrchr(sp,'/');
287                 if( bp ) sp = bp+1;
288                 while( cp < ep && *sp != 0 ) {
289                         *cp++ = (*sp>='a' && *sp<='z') ||
290                                 (*sp>='A' && *sp<='Z') ||
291                                 (*sp>='0' && *sp<='9') ? *sp : '_';
292                         ++sp;
293                 }
294         }
295         *cp = 0;
296
297         gui->tracking_file->update(plugin->config.tracking_file);
298         plugin->reset_cache_file();
299
300 // Revert tracking type to not using tracking file
301         if( plugin->config.tracking_type == MotionScan::LOAD ||
302             plugin->config.tracking_type == MotionScan::SAVE )
303         {
304                 plugin->config.tracking_type = MotionScan::NO_CALCULATE;
305                 gui->tracking_type->set_text(TrackingType::to_text(plugin->config.tracking_type));
306         }
307
308         plugin->send_configure_change();
309         return 1;
310 }
311
312 MotionClearTracking::MotionClearTracking(MotionMain *plugin, MotionWindow *gui, int x, int y)
313  : BC_GenericButton(x, y, _("Clear tracking file contents"))
314 {
315         this->plugin = plugin;
316         this->gui = gui;
317 };
318
319 int MotionClearTracking::handle_event()
320 {
321         char save_file[BCTEXTLEN];
322
323 // First of all, ensure closing current tracking file
324         plugin->reset_cache_file();
325
326 // Suffix .bak not allowed: reserved for intermediate tracking file copy
327         snprintf(save_file, sizeof(save_file), "%s.old", plugin->config.tracking_file);
328         ::rename(plugin->config.tracking_file, save_file);
329
330 // Just for safety
331         ::remove(plugin->config.tracking_file);
332         plugin->reset_cache_file();
333
334         return 1;
335 }
336
337 MotionFrameCurrent::MotionFrameCurrent(MotionMain *plugin, MotionWindow *gui, int x, int y)
338  : BC_GenericButton(x, y, _("Get current"))
339 {
340         this->plugin = plugin;
341         this->gui = gui;
342 };
343
344 int MotionFrameCurrent::handle_event()
345 {
346         plugin->config.track_frame = plugin->get_source_position();
347         gui->track_frame_number->update(plugin->config.track_frame);
348         plugin->send_configure_change();
349         return 1;
350 }
351
352
353 GlobalRange::GlobalRange(MotionMain *plugin,
354         int x, int y, int *value)
355  : BC_IPot(x, y, (int64_t)*value,
356         (int64_t)MIN_RADIUS, (int64_t)MAX_RADIUS)
357 {
358         this->plugin = plugin;
359         this->value = value;
360 }
361
362
363 int GlobalRange::handle_event()
364 {
365         *value = (int)get_value();
366         plugin->send_configure_change();
367         return 1;
368 }
369
370
371
372
373 RotationRange::RotationRange(MotionMain *plugin, int x, int y)
374  : BC_IPot(x, y, (int64_t)plugin->config.rotation_range,
375         (int64_t)MIN_ROTATION, (int64_t)MAX_ROTATION)
376 {
377         this->plugin = plugin;
378 }
379
380
381 int RotationRange::handle_event()
382 {
383         plugin->config.rotation_range = (int)get_value();
384         plugin->send_configure_change();
385         return 1;
386 }
387
388
389 RotationCenter::RotationCenter(MotionMain *plugin, int x, int y)
390  : BC_IPot(x, y, (int64_t)plugin->config.rotation_center,
391         (int64_t)-MAX_ROTATION, (int64_t)MAX_ROTATION)
392 {
393         this->plugin = plugin;
394 }
395
396
397 int RotationCenter::handle_event()
398 {
399         plugin->config.rotation_center = (int)get_value();
400         plugin->send_configure_change();
401         return 1;
402 }
403
404
405 BlockSize::BlockSize(MotionMain *plugin,
406         int x,
407         int y,
408         int *value)
409  : BC_IPot(x,
410                 y,
411                 (int64_t)*value,
412                 (int64_t)MIN_BLOCK,
413                 (int64_t)MAX_BLOCK)
414 {
415         this->plugin = plugin;
416         this->value = value;
417 }
418
419
420 int BlockSize::handle_event()
421 {
422         *value = (int)get_value();
423         plugin->send_configure_change();
424         return 1;
425 }
426
427
428 GlobalSearchPositions::GlobalSearchPositions(MotionMain *plugin,
429         int x, int y, int w)
430  : BC_PopupMenu(x, y, w, "", 1)
431 {
432         this->plugin = plugin;
433 }
434 void GlobalSearchPositions::create_objects()
435 {
436         add_item(new BC_MenuItem("16"));
437         add_item(new BC_MenuItem("32"));
438         add_item(new BC_MenuItem("64"));
439         add_item(new BC_MenuItem("128"));
440         add_item(new BC_MenuItem("256"));
441         add_item(new BC_MenuItem("512"));
442         add_item(new BC_MenuItem("1024"));
443         add_item(new BC_MenuItem("2048"));
444         add_item(new BC_MenuItem("4096"));
445         add_item(new BC_MenuItem("8192"));
446         add_item(new BC_MenuItem("16384"));
447         add_item(new BC_MenuItem("32768"));
448         add_item(new BC_MenuItem("65536"));
449         add_item(new BC_MenuItem("131072"));
450         char string[BCTEXTLEN];
451         sprintf(string, "%d", plugin->config.global_positions);
452         set_text(string);
453 }
454
455 int GlobalSearchPositions::handle_event()
456 {
457         plugin->config.global_positions = atoi(get_text());
458         plugin->send_configure_change();
459         return 1;
460 }
461
462
463 RotationSearchPositions::RotationSearchPositions(MotionMain *plugin,
464         int x, int y, int w)
465  : BC_PopupMenu(x, y, w, "", 1)
466 {
467         this->plugin = plugin;
468 }
469 void RotationSearchPositions::create_objects()
470 {
471         add_item(new BC_MenuItem("4"));
472         add_item(new BC_MenuItem("8"));
473         add_item(new BC_MenuItem("16"));
474         add_item(new BC_MenuItem("32"));
475         char string[BCTEXTLEN];
476         sprintf(string, "%d", plugin->config.rotate_positions);
477         set_text(string);
478 }
479
480 int RotationSearchPositions::handle_event()
481 {
482         plugin->config.rotate_positions = atoi(get_text());
483         plugin->send_configure_change();
484         return 1;
485 }
486
487
488 MotionMagnitude::MotionMagnitude(MotionMain *plugin, int x, int y)
489  : BC_IPot(x, y,
490         (int64_t)plugin->config.magnitude, (int64_t)0, (int64_t)100)
491 {
492         this->plugin = plugin;
493 }
494
495 int MotionMagnitude::handle_event()
496 {
497         plugin->config.magnitude = (int)get_value();
498         plugin->send_configure_change();
499         return 1;
500 }
501
502
503 MotionReturnSpeed::MotionReturnSpeed(MotionMain *plugin, int x, int y)
504  : BC_IPot(x, y,
505         (int64_t)plugin->config.return_speed, (int64_t)0, (int64_t)100)
506 {
507         this->plugin = plugin;
508 }
509
510 int MotionReturnSpeed::handle_event()
511 {
512         plugin->config.return_speed = (int)get_value();
513         plugin->send_configure_change();
514         return 1;
515 }
516
517
518
519 AddTrackedFrameOffset::AddTrackedFrameOffset(MotionMain *plugin,
520         MotionWindow *gui, int x, int y)
521  : BC_CheckBox(x, y, plugin->config.addtrackedframeoffset,
522         _("Add (loaded) offset from tracked frame"))
523 {
524         this->plugin = plugin;
525         this->gui = gui;
526 }
527
528 int AddTrackedFrameOffset::handle_event()
529 {
530         plugin->config.addtrackedframeoffset = get_value();
531         plugin->send_configure_change();
532         return 1;
533 }
534
535
536 MotionRMagnitude::MotionRMagnitude(MotionMain *plugin, int x, int y)
537  : BC_IPot(x, y,
538         (int64_t)plugin->config.rotate_magnitude, (int64_t)0, (int64_t)90)
539 {
540         this->plugin = plugin;
541 }
542
543 int MotionRMagnitude::handle_event()
544 {
545         plugin->config.rotate_magnitude = (int)get_value();
546         plugin->send_configure_change();
547         return 1;
548 }
549
550
551
552 MotionRReturnSpeed::MotionRReturnSpeed(MotionMain *plugin, int x, int y)
553  : BC_IPot(x, y,
554         (int64_t)plugin->config.rotate_return_speed, (int64_t)0, (int64_t)100)
555 {
556         this->plugin = plugin;
557 }
558
559 int MotionRReturnSpeed::handle_event()
560 {
561         plugin->config.rotate_return_speed = (int)get_value();
562         plugin->send_configure_change();
563         return 1;
564 }
565
566
567 MotionGlobal::MotionGlobal(MotionMain *plugin,
568         MotionWindow *gui, int x, int y)
569  : BC_CheckBox(x, y, plugin->config.global, _("Track translation"))
570 {
571         this->plugin = plugin;
572         this->gui = gui;
573 }
574
575 int MotionGlobal::handle_event()
576 {
577         plugin->config.global = get_value();
578         plugin->send_configure_change();
579         return 1;
580 }
581
582 MotionRotate::MotionRotate(MotionMain *plugin,
583         MotionWindow *gui, int x, int y)
584  : BC_CheckBox(x, y, plugin->config.rotate, _("Track rotation"))
585 {
586         this->plugin = plugin;
587         this->gui = gui;
588 }
589
590 int MotionRotate::handle_event()
591 {
592         plugin->config.rotate = get_value();
593         plugin->send_configure_change();
594         return 1;
595 }
596
597 MotionTwopass::MotionTwopass(MotionMain *plugin, 
598         MotionWindow *gui, int x, int y)
599  : BC_CheckBox(x, y, plugin->config.twopass, _("Two pass tracking"))
600 {
601         this->plugin = plugin;
602         this->gui = gui;
603 }
604
605 int MotionTwopass::handle_event()
606 {
607         plugin->config.twopass = get_value();
608         plugin->send_configure_change();
609         return 1;
610 }
611
612
613 MotionBlockX::MotionBlockX(MotionMain *plugin,
614         MotionWindow *gui, int x, int y)
615  : BC_FPot(x, y, plugin->config.block_x, (float)0, (float)100)
616 {
617         this->plugin = plugin;
618         this->gui = gui;
619 }
620
621 int MotionBlockX::handle_event()
622 {
623         plugin->config.block_x = get_value();
624         gui->block_x_text->update((float)plugin->config.block_x);
625         plugin->send_configure_change();
626         return 1;
627 }
628
629
630 MotionBlockY::MotionBlockY(MotionMain *plugin,
631         MotionWindow *gui,
632         int x,
633         int y)
634  : BC_FPot(x,
635         y,
636         (float)plugin->config.block_y,
637         (float)0,
638         (float)100)
639 {
640         this->plugin = plugin;
641         this->gui = gui;
642 }
643
644 int MotionBlockY::handle_event()
645 {
646         plugin->config.block_y = get_value();
647         gui->block_y_text->update((float)plugin->config.block_y);
648         plugin->send_configure_change();
649         return 1;
650 }
651
652 MotionBlockXText::MotionBlockXText(MotionMain *plugin,
653         MotionWindow *gui, int x, int y)
654  : BC_TextBox(x, y, xS(75), 1, (float)plugin->config.block_x)
655 {
656         this->plugin = plugin;
657         this->gui = gui;
658         set_precision(4);
659 }
660
661 int MotionBlockXText::handle_event()
662 {
663         plugin->config.block_x = atof(get_text());
664         gui->block_x->update(plugin->config.block_x);
665         plugin->send_configure_change();
666         return 1;
667 }
668
669
670
671
672 MotionBlockYText::MotionBlockYText(MotionMain *plugin,
673         MotionWindow *gui, int x, int y)
674  : BC_TextBox(x, y, xS(75), 1, (float)plugin->config.block_y)
675 {
676         this->plugin = plugin;
677         this->gui = gui;
678         set_precision(4);
679 }
680
681 int MotionBlockYText::handle_event()
682 {
683         plugin->config.block_y = atof(get_text());
684         gui->block_y->update(plugin->config.block_y);
685         plugin->send_configure_change();
686         return 1;
687 }
688
689
690 MotionNoiseLevel::MotionNoiseLevel(MotionMain *plugin, 
691         MotionWindow *gui, int x, int y)
692  : BC_FPot(x, y, plugin->config.noise_level, (float)0, (float)100)
693 {
694         this->plugin = plugin;
695         this->gui = gui;
696 }
697
698 int MotionNoiseLevel::handle_event()
699 {
700         float level = plugin->config.noise_level;
701         level = get_value();
702         if (level < 0)   level = 0;
703         if (level > 100) level = 100;
704         plugin->config.noise_level = level;
705         gui->noise_level_text->update((float)plugin->config.noise_level);
706         plugin->send_configure_change();
707         return 1;
708 }
709
710 MotionNoiseLevelText::MotionNoiseLevelText(MotionMain *plugin, 
711         MotionWindow *gui, int x, int y)
712  : BC_TextBox(x, y, xS(75), 1, (float)plugin->config.noise_level)
713 {
714         this->plugin = plugin;
715         this->gui = gui;
716         set_precision(4);
717 }
718
719 int MotionNoiseLevelText::handle_event()
720 {
721         float level = plugin->config.noise_level;
722         level = atof(get_text());
723         if (level < 0)   level = 0;
724         if (level > 100) level = 100;
725         plugin->config.noise_level = level;
726         gui->noise_level->update(plugin->config.noise_level);
727         plugin->send_configure_change();
728         return 1;
729 }
730
731 MotionNoiseRotation::MotionNoiseRotation(MotionMain *plugin, 
732         MotionWindow *gui, int x, int y)
733  : BC_FPot(x, y, plugin->config.noise_rotation, (float)0, (float)100)
734 {
735         this->plugin = plugin;
736         this->gui = gui;
737 }
738
739 int MotionNoiseRotation::handle_event()
740 {
741         float level = plugin->config.noise_rotation;
742         level = get_value();
743         if (level < 0)   level = 0;
744         if (level > 100) level = 100;
745         plugin->config.noise_rotation = level;
746         gui->noise_rotation_text->update((float)plugin->config.noise_rotation);
747         plugin->send_configure_change();
748         return 1;
749 }
750
751 MotionNoiseRotationText::MotionNoiseRotationText(MotionMain *plugin, 
752         MotionWindow *gui, int x, int y)
753  : BC_TextBox(x, y, xS(75), 1, (float)plugin->config.noise_rotation)
754 {
755         this->plugin = plugin;
756         this->gui = gui;
757         set_precision(4);
758 }
759
760 int MotionNoiseRotationText::handle_event()
761 {
762         float level = plugin->config.noise_rotation;
763         level = atof(get_text());
764         if (level < 0)   level = 0;
765         if (level > 100) level = 100;
766         plugin->config.noise_rotation = level;
767         gui->noise_rotation->update(plugin->config.noise_rotation);
768         plugin->send_configure_change();
769         return 1;
770 }
771
772
773 MotionDrawVectors::MotionDrawVectors(MotionMain *plugin,
774         MotionWindow *gui, int x, int y)
775  : BC_CheckBox(x,
776         y,
777         plugin->config.draw_vectors,
778         _("Draw vectors"))
779 {
780         this->gui = gui;
781         this->plugin = plugin;
782 }
783
784 int MotionDrawVectors::handle_event()
785 {
786         plugin->config.draw_vectors = get_value();
787         plugin->send_configure_change();
788         return 1;
789 }
790
791
792 TrackSingleFrame::TrackSingleFrame(MotionMain *plugin,
793         MotionWindow *gui,
794         int x,
795         int y)
796  : BC_Radial(x,
797         y,
798         plugin->config.tracking_object == MotionScan::TRACK_SINGLE,
799         _("Track single frame"))
800 {
801         this->plugin = plugin;
802         this->gui = gui;
803 }
804
805 int TrackSingleFrame::handle_event()
806 {
807         plugin->config.tracking_object = MotionScan::TRACK_SINGLE;
808         gui->track_previous->update(0);
809         gui->previous_same->update(0);
810         gui->track_frame_number->enable();
811         gui->frame_current->enable();
812         plugin->send_configure_change();
813         return 1;
814 }
815
816 TrackFrameNumber::TrackFrameNumber(MotionMain *plugin,
817         MotionWindow *gui,
818         int x,
819         int y)
820  : BC_TextBox(x, y, xS(100), 1, plugin->config.track_frame)
821 {
822         this->plugin = plugin;
823         this->gui = gui;
824 }
825
826 int TrackFrameNumber::handle_event()
827 {
828         plugin->config.track_frame = atol(get_text());
829         plugin->send_configure_change();
830         return 1;
831 }
832
833
834 TrackPreviousFrame::TrackPreviousFrame(MotionMain *plugin,
835         MotionWindow *gui,
836         int x,
837         int y)
838  : BC_Radial(x,
839         y,
840         plugin->config.tracking_object == MotionScan::TRACK_PREVIOUS,
841         _("Track previous frame"))
842 {
843         this->plugin = plugin;
844         this->gui = gui;
845 }
846 int TrackPreviousFrame::handle_event()
847 {
848         plugin->config.tracking_object = MotionScan::TRACK_PREVIOUS;
849         gui->track_single->update(0);
850         gui->previous_same->update(0);
851         gui->track_frame_number->disable();
852         gui->frame_current->disable();
853         plugin->send_configure_change();
854         return 1;
855 }
856
857
858 PreviousFrameSameBlock::PreviousFrameSameBlock(MotionMain *plugin,
859         MotionWindow *gui,
860         int x,
861         int y)
862  : BC_Radial(x,
863         y,
864         plugin->config.tracking_object == MotionScan::PREVIOUS_SAME_BLOCK,
865         _("Previous frame same block"))
866 {
867         this->plugin = plugin;
868         this->gui = gui;
869 }
870 int PreviousFrameSameBlock::handle_event()
871 {
872         plugin->config.tracking_object = MotionScan::PREVIOUS_SAME_BLOCK;
873         gui->track_single->update(0);
874         gui->track_previous->update(0);
875         gui->track_frame_number->disable();
876         gui->frame_current->disable();
877         plugin->send_configure_change();
878         return 1;
879 }
880
881
882 MasterLayer::MasterLayer(MotionMain *plugin, MotionWindow *gui, int x, int y)
883  : BC_PopupMenu(x,
884         y,
885         calculate_w(gui),
886         to_text(plugin->config.bottom_is_master))
887 {
888         this->plugin = plugin;
889         this->gui = gui;
890 }
891
892 int MasterLayer::handle_event()
893 {
894         plugin->config.bottom_is_master = from_text(get_text());
895         plugin->send_configure_change();
896         return 1;
897 }
898
899 void MasterLayer::create_objects()
900 {
901         add_item(new BC_MenuItem(to_text(0)));
902         add_item(new BC_MenuItem(to_text(1)));
903 }
904
905 int MasterLayer::from_text(char *text)
906 {
907         if(!strcmp(text, _("Top"))) return 0;
908         return 1;
909 }
910
911 char* MasterLayer::to_text(int mode)
912 {
913         return mode ? _("Bottom") : _("Top");
914 }
915
916 int MasterLayer::calculate_w(MotionWindow *gui)
917 {
918         int result = 0;
919         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0)));
920         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(1)));
921         return result + xS(80);
922 }
923
924
925 ActionType::ActionType(MotionMain *plugin, MotionWindow *gui, int x, int y)
926  : BC_PopupMenu(x,
927         y,
928         calculate_w(gui),
929         to_text(plugin->config.action_type))
930 {
931         this->plugin = plugin;
932         this->gui = gui;
933 }
934
935 int ActionType::handle_event()
936 {
937         plugin->config.action_type = from_text(get_text());
938         plugin->send_configure_change();
939         return 1;
940 }
941
942 void ActionType::create_objects()
943 {
944         add_item(new BC_MenuItem(to_text(MotionScan::TRACK)));
945         add_item(new BC_MenuItem(to_text(MotionScan::TRACK_PIXEL)));
946         add_item(new BC_MenuItem(to_text(MotionScan::STABILIZE)));
947         add_item(new BC_MenuItem(to_text(MotionScan::STABILIZE_PIXEL)));
948         add_item(new BC_MenuItem(to_text(MotionScan::NOTHING)));
949 }
950
951 int ActionType::from_text(char *text)
952 {
953         if(!strcmp(text, _("Track Subpixel"))) return MotionScan::TRACK;
954         if(!strcmp(text, _("Track Pixel"))) return MotionScan::TRACK_PIXEL;
955         if(!strcmp(text, _("Stabilize Subpixel"))) return MotionScan::STABILIZE;
956         if(!strcmp(text, _("Stabilize Pixel"))) return MotionScan::STABILIZE_PIXEL;
957         //if(!strcmp(text, _("Do Nothing"))) return MotionScan::NOTHING;
958         return MotionScan::NOTHING;
959 }
960
961 char* ActionType::to_text(int mode)
962 {
963         switch(mode)
964         {
965                 case MotionScan::TRACK:
966                         return _("Track Subpixel");
967                 case MotionScan::TRACK_PIXEL:
968                         return _("Track Pixel");
969                 case MotionScan::STABILIZE:
970                         return _("Stabilize Subpixel");
971                 case MotionScan::STABILIZE_PIXEL:
972                         return _("Stabilize Pixel");
973                 default:
974                 case MotionScan::NOTHING:
975                         return _("Do Nothing");
976         }
977 }
978
979 int ActionType::calculate_w(MotionWindow *gui)
980 {
981         int result = 0;
982         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::TRACK)));
983         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::TRACK_PIXEL)));
984         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::STABILIZE)));
985         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::STABILIZE_PIXEL)));
986         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::NOTHING)));
987         return result + xS(80);
988 }
989
990
991 TrackingType::TrackingType(MotionMain *plugin, MotionWindow *gui, int x, int y)
992  : BC_PopupMenu(x,
993         y,
994         calculate_w(gui),
995         to_text(plugin->config.tracking_type))
996 {
997         this->plugin = plugin;
998         this->gui = gui;
999 }
1000
1001 int TrackingType::handle_event()
1002 {
1003         plugin->config.tracking_type = from_text(get_text());
1004         plugin->send_configure_change();
1005         return 1;
1006 }
1007
1008 void TrackingType::create_objects()
1009 {
1010         add_item(new BC_MenuItem(to_text(MotionScan::SAVE)));
1011         add_item(new BC_MenuItem(to_text(MotionScan::LOAD)));
1012         add_item(new BC_MenuItem(to_text(MotionScan::CALCULATE)));
1013         add_item(new BC_MenuItem(to_text(MotionScan::NO_CALCULATE)));
1014 }
1015
1016 int TrackingType::from_text(char *text)
1017 {
1018         if(!strcmp(text, _("Save coords to tracking file"))) return MotionScan::SAVE;
1019         if(!strcmp(text, _("Load coords from tracking file"))) return MotionScan::LOAD;
1020         if(!strcmp(text, _("Recalculate"))) return MotionScan::CALCULATE;
1021         //if(!strcmp(text, _("Don't Calculate"))) return MotionScan::NO_CALCULATE;
1022         return MotionScan::NO_CALCULATE;
1023 }
1024
1025 char* TrackingType::to_text(int mode)
1026 {
1027         switch(mode)
1028         {
1029                 case MotionScan::SAVE:          return _("Save coords to tracking file");
1030                 case MotionScan::LOAD:          return _("Load coords from tracking file");
1031                 case MotionScan::CALCULATE:     return _("Recalculate");
1032                 default:
1033                 case MotionScan::NO_CALCULATE:  return _("Don't Calculate");
1034         }
1035 }
1036
1037 int TrackingType::calculate_w(MotionWindow *gui)
1038 {
1039         int result = 0;
1040         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::NO_CALCULATE)));
1041         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::CALCULATE)));
1042         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::SAVE)));
1043         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::LOAD)));
1044         return result + xS(80);
1045 }
1046
1047
1048 TrackDirection::TrackDirection(MotionMain *plugin, MotionWindow *gui, int x, int y)
1049  : BC_PopupMenu(x,
1050         y,
1051         calculate_w(gui),
1052         to_text(plugin->config.horizontal_only, plugin->config.vertical_only))
1053 {
1054         this->plugin = plugin;
1055         this->gui = gui;
1056 }
1057
1058 int TrackDirection::handle_event()
1059 {
1060         from_text(&plugin->config.horizontal_only, &plugin->config.vertical_only, get_text());
1061         plugin->send_configure_change();
1062         return 1;
1063 }
1064
1065 void TrackDirection::create_objects()
1066 {
1067         add_item(new BC_MenuItem(to_text(1, 0)));
1068         add_item(new BC_MenuItem(to_text(0, 1)));
1069         add_item(new BC_MenuItem(to_text(0, 0)));
1070 }
1071
1072 void TrackDirection::from_text(int *horizontal_only, int *vertical_only, char *text)
1073 {
1074         *horizontal_only = 0;
1075         *vertical_only = 0;
1076         if(!strcmp(text, to_text(1, 0))) *horizontal_only = 1;
1077         if(!strcmp(text, to_text(0, 1))) *vertical_only = 1;
1078 }
1079
1080 char* TrackDirection::to_text(int horizontal_only, int vertical_only)
1081 {
1082         if(horizontal_only) return _("Horizontal only");
1083         if(vertical_only) return _("Vertical only");
1084         return _("Both");
1085 }
1086
1087 int TrackDirection::calculate_w(MotionWindow *gui)
1088 {
1089         int result = 0;
1090         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(1, 0)));
1091         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0, 1)));
1092         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0, 0)));
1093         return result + xS(80);
1094 }
1095