resourcethread redraw speedup/fixes, replace vectorscope graticule IQ
[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(640), xS(800), yS(640), 0)
36 {
37         this->plugin = plugin;
38 }
39
40 MotionWindow::~MotionWindow()
41 {
42 }
43
44 void MotionWindow::create_objects()
45 {
46         int xs5 = xS(5), 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), ys60 = yS(60);
48         int x = xs10, y = ys10;
49         int x1 = x, x2 = get_w() / 2;
50         BC_Title *title;
51
52         add_subwindow(global = new MotionGlobal(plugin, this, x1, y));
53         add_subwindow(rotate = new MotionRotate(plugin, this, x2, y));
54         y += ys50;
55
56         add_subwindow(title = new BC_Title(x1, y,
57                 _("Translation search radius:\n(W/H Percent of image)")));
58         add_subwindow(global_range_w = new GlobalRange(plugin,
59                 x1 + title->get_w() + xs10, y,
60                 &plugin->config.global_range_w));
61         add_subwindow(global_range_h = new GlobalRange(plugin,
62                 x1 + 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(x1, y,
72                 _("Translation block size:\n(W/H Percent of image)")));
73         add_subwindow(global_block_w =
74                 new BlockSize(plugin, x1 + title->get_w() + xs10, y,
75                 &plugin->config.global_block_w));
76         add_subwindow(global_block_h =
77                 new BlockSize(plugin, x1 + 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(x1, y, _("Translation search steps:")));
95         add_subwindow(global_search_positions =
96                 new GlobalSearchPositions(plugin, x1 + 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(x2, y, _("Tracking file:")));
114         add_subwindow(tracking_file = new MotionTrackingFile(plugin,
115                 plugin->config.tracking_file, this, x2+title->get_w() + xs20, y));
116
117         int y1 = y;
118         add_subwindow(title = new BC_Title(x, y + ys10, _("Block X:")));
119         add_subwindow(block_x =
120                 new MotionBlockX(plugin, this, x + title->get_w() + xs10, y));
121         add_subwindow(block_x_text =
122                 new MotionBlockXText(plugin, this,
123                         x + title->get_w() + xs10 + block_x->get_w() + xs10, y + ys10));
124
125         y += ys40;
126         add_subwindow(title = new BC_Title(x2, y, _("Rotation center:")));
127         add_subwindow(rotation_center =
128                 new RotationCenter(plugin, x2 + title->get_w() + xs10, y));
129
130         y += ys40;
131         add_subwindow(title = new BC_Title(x2, y + ys10, _("Maximum angle offset:")));
132         add_subwindow(rotate_magnitude =
133                 new MotionRMagnitude(plugin, x2 + title->get_w() + xs10, y));
134
135         y += ys40;
136         add_subwindow(title = new BC_Title(x2, y + ys10, _("Rotation settling speed:")));
137         add_subwindow(rotate_return_speed =
138                 new MotionRReturnSpeed(plugin, x2 + title->get_w() + xs10, y));
139         y += ys40;
140         add_subwindow(vectors = new MotionDrawVectors(plugin, this, x2, y));
141
142         y = y1 + ys60;
143         add_subwindow(title = new BC_Title(x, y + ys10, _("Block Y:")));
144         add_subwindow(block_y =
145                 new MotionBlockY(plugin, this, x + title->get_w() + xs10, y));
146         add_subwindow(block_y_text =
147                 new MotionBlockYText(plugin, this,
148                         x + title->get_w() + xs10 + block_y->get_w() + xs10, y + ys10));
149
150         y += ys50;
151         add_subwindow(title = new BC_Title(x, y + ys10, _("Maximum absolute offset:")));
152         add_subwindow(magnitude = new MotionMagnitude(plugin,
153                 x + title->get_w() + xs10,
154                 y));
155
156         y += ys40;
157         add_subwindow(title = new BC_Title(x, y + ys10, _("Motion settling speed:")));
158         add_subwindow(return_speed =
159                 new MotionReturnSpeed(plugin, x + title->get_w() + xs10, y));
160
161         y += ys40;
162         add_subwindow(track_single =
163                 new TrackSingleFrame(plugin, this, x, y));
164         y += ys20;
165         add_subwindow(track_previous =
166                 new TrackPreviousFrame(plugin, this, x, y));
167         y += ys20;
168         add_subwindow(previous_same =
169                 new PreviousFrameSameBlock(plugin, this, x, y));
170
171         y += ys40;
172         x1 = x;  y1 = y;
173         add_subwindow(title =
174                 new BC_Title(x1=x2, y1, _("Frame number:")));
175         add_subwindow(track_frame_number =
176                 new TrackFrameNumber(plugin, this, x1 += title->get_w(), y1));
177         if(plugin->config.tracking_object != MotionScan::TRACK_SINGLE)
178                 track_frame_number->disable();
179
180         add_subwindow(addtrackedframeoffset =
181                 new AddTrackedFrameOffset(plugin, this, x1=x2, y1+=track_frame_number->get_h()));
182         int pef = client->server->mwindow->edl->session->video_every_frame;
183         add_subwindow(pef_title = new BC_Title(x1=x2+xs50, y1+=addtrackedframeoffset->get_h() + xs5,
184                 !pef ?  _("For best results\n"
185                                 " Set: Play every frame\n"
186                                 " Preferences-> Playback-> Video Out") :
187                         _("Currently using: Play every frame"), MEDIUMFONT,
188                 !pef ? RED : GREEN));
189
190         add_subwindow(title = new BC_Title(x, y, _("Master layer:")));
191         add_subwindow(master_layer = new MasterLayer(plugin,
192                 this, x + title->get_w() + xs10, y));
193         master_layer->create_objects();
194         y += ys30;
195
196         add_subwindow(title = new BC_Title(x, y, _("Action:")));
197         add_subwindow(action_type = new ActionType(plugin,
198                 this, x + title->get_w() + xs10, y));
199         action_type->create_objects();
200         y += ys30;
201
202         add_subwindow(title = new BC_Title(x, y, _("Calculation:")));
203         add_subwindow(tracking_type = new TrackingType(plugin,
204                 this, x + title->get_w() + xs10, y));
205         tracking_type->create_objects();
206
207         show_window(1);
208 }
209
210 void MotionWindow::update_mode()
211 {
212         global_range_w->update(plugin->config.global_range_w,
213                 MIN_RADIUS, MAX_RADIUS);
214         global_range_h->update(plugin->config.global_range_h,
215                 MIN_RADIUS, MAX_RADIUS);
216         rotation_range->update(plugin->config.rotation_range,
217                 MIN_ROTATION, MAX_ROTATION);
218         vectors->update(plugin->config.draw_vectors);
219         tracking_file->update(plugin->config.tracking_file);
220         global->update(plugin->config.global);
221         rotate->update(plugin->config.rotate);
222         addtrackedframeoffset->update(plugin->config.addtrackedframeoffset);
223 }
224
225 MotionTrackingFile::MotionTrackingFile(MotionMain *plugin,
226         const char *filename, MotionWindow *gui, int x, int y)
227  : BC_TextBox(x, y, xS(150), 1, filename)
228 {
229         this->plugin = plugin;
230         this->gui = gui;
231 };
232
233 int MotionTrackingFile::handle_event()
234 {
235         strcpy(plugin->config.tracking_file, get_text());
236         plugin->send_configure_change();
237         return 1;
238 }
239
240
241 GlobalRange::GlobalRange(MotionMain *plugin,
242         int x, int y, int *value)
243  : BC_IPot(x, y, (int64_t)*value,
244         (int64_t)MIN_RADIUS, (int64_t)MAX_RADIUS)
245 {
246         this->plugin = plugin;
247         this->value = value;
248 }
249
250
251 int GlobalRange::handle_event()
252 {
253         *value = (int)get_value();
254         plugin->send_configure_change();
255         return 1;
256 }
257
258
259
260
261 RotationRange::RotationRange(MotionMain *plugin, int x, int y)
262  : BC_IPot(x, y, (int64_t)plugin->config.rotation_range,
263         (int64_t)MIN_ROTATION, (int64_t)MAX_ROTATION)
264 {
265         this->plugin = plugin;
266 }
267
268
269 int RotationRange::handle_event()
270 {
271         plugin->config.rotation_range = (int)get_value();
272         plugin->send_configure_change();
273         return 1;
274 }
275
276
277 RotationCenter::RotationCenter(MotionMain *plugin, int x, int y)
278  : BC_IPot(x, y, (int64_t)plugin->config.rotation_center,
279         (int64_t)-MAX_ROTATION, (int64_t)MAX_ROTATION)
280 {
281         this->plugin = plugin;
282 }
283
284
285 int RotationCenter::handle_event()
286 {
287         plugin->config.rotation_center = (int)get_value();
288         plugin->send_configure_change();
289         return 1;
290 }
291
292
293 BlockSize::BlockSize(MotionMain *plugin,
294         int x,
295         int y,
296         int *value)
297  : BC_IPot(x,
298                 y,
299                 (int64_t)*value,
300                 (int64_t)MIN_BLOCK,
301                 (int64_t)MAX_BLOCK)
302 {
303         this->plugin = plugin;
304         this->value = value;
305 }
306
307
308 int BlockSize::handle_event()
309 {
310         *value = (int)get_value();
311         plugin->send_configure_change();
312         return 1;
313 }
314
315
316 GlobalSearchPositions::GlobalSearchPositions(MotionMain *plugin,
317         int x, int y, int w)
318  : BC_PopupMenu(x, y, w, "", 1)
319 {
320         this->plugin = plugin;
321 }
322 void GlobalSearchPositions::create_objects()
323 {
324         add_item(new BC_MenuItem("16"));
325         add_item(new BC_MenuItem("32"));
326         add_item(new BC_MenuItem("64"));
327         add_item(new BC_MenuItem("128"));
328         add_item(new BC_MenuItem("256"));
329         add_item(new BC_MenuItem("512"));
330         add_item(new BC_MenuItem("1024"));
331         add_item(new BC_MenuItem("2048"));
332         add_item(new BC_MenuItem("4096"));
333         add_item(new BC_MenuItem("8192"));
334         add_item(new BC_MenuItem("16384"));
335         add_item(new BC_MenuItem("32768"));
336         add_item(new BC_MenuItem("65536"));
337         add_item(new BC_MenuItem("131072"));
338         char string[BCTEXTLEN];
339         sprintf(string, "%d", plugin->config.global_positions);
340         set_text(string);
341 }
342
343 int GlobalSearchPositions::handle_event()
344 {
345         plugin->config.global_positions = atoi(get_text());
346         plugin->send_configure_change();
347         return 1;
348 }
349
350
351 RotationSearchPositions::RotationSearchPositions(MotionMain *plugin,
352         int x, int y, int w)
353  : BC_PopupMenu(x, y, w, "", 1)
354 {
355         this->plugin = plugin;
356 }
357 void RotationSearchPositions::create_objects()
358 {
359         add_item(new BC_MenuItem("4"));
360         add_item(new BC_MenuItem("8"));
361         add_item(new BC_MenuItem("16"));
362         add_item(new BC_MenuItem("32"));
363         char string[BCTEXTLEN];
364         sprintf(string, "%d", plugin->config.rotate_positions);
365         set_text(string);
366 }
367
368 int RotationSearchPositions::handle_event()
369 {
370         plugin->config.rotate_positions = atoi(get_text());
371         plugin->send_configure_change();
372         return 1;
373 }
374
375
376 MotionMagnitude::MotionMagnitude(MotionMain *plugin, int x, int y)
377  : BC_IPot(x, y,
378         (int64_t)plugin->config.magnitude, (int64_t)0, (int64_t)100)
379 {
380         this->plugin = plugin;
381 }
382
383 int MotionMagnitude::handle_event()
384 {
385         plugin->config.magnitude = (int)get_value();
386         plugin->send_configure_change();
387         return 1;
388 }
389
390
391 MotionReturnSpeed::MotionReturnSpeed(MotionMain *plugin, int x, int y)
392  : BC_IPot(x, y,
393         (int64_t)plugin->config.return_speed, (int64_t)0, (int64_t)100)
394 {
395         this->plugin = plugin;
396 }
397
398 int MotionReturnSpeed::handle_event()
399 {
400         plugin->config.return_speed = (int)get_value();
401         plugin->send_configure_change();
402         return 1;
403 }
404
405
406
407 AddTrackedFrameOffset::AddTrackedFrameOffset(MotionMain *plugin,
408         MotionWindow *gui, int x, int y)
409  : BC_CheckBox(x, y, plugin->config.addtrackedframeoffset,
410         _("Add (loaded) offset from tracked frame"))
411 {
412         this->plugin = plugin;
413         this->gui = gui;
414 }
415
416 int AddTrackedFrameOffset::handle_event()
417 {
418         plugin->config.addtrackedframeoffset = get_value();
419         plugin->send_configure_change();
420         return 1;
421 }
422
423
424 MotionRMagnitude::MotionRMagnitude(MotionMain *plugin, int x, int y)
425  : BC_IPot(x, y,
426         (int64_t)plugin->config.rotate_magnitude, (int64_t)0, (int64_t)90)
427 {
428         this->plugin = plugin;
429 }
430
431 int MotionRMagnitude::handle_event()
432 {
433         plugin->config.rotate_magnitude = (int)get_value();
434         plugin->send_configure_change();
435         return 1;
436 }
437
438
439
440 MotionRReturnSpeed::MotionRReturnSpeed(MotionMain *plugin, int x, int y)
441  : BC_IPot(x, y,
442         (int64_t)plugin->config.rotate_return_speed, (int64_t)0, (int64_t)100)
443 {
444         this->plugin = plugin;
445 }
446
447 int MotionRReturnSpeed::handle_event()
448 {
449         plugin->config.rotate_return_speed = (int)get_value();
450         plugin->send_configure_change();
451         return 1;
452 }
453
454
455 MotionGlobal::MotionGlobal(MotionMain *plugin,
456         MotionWindow *gui, int x, int y)
457  : BC_CheckBox(x, y, plugin->config.global, _("Track translation"))
458 {
459         this->plugin = plugin;
460         this->gui = gui;
461 }
462
463 int MotionGlobal::handle_event()
464 {
465         plugin->config.global = get_value();
466         plugin->send_configure_change();
467         return 1;
468 }
469
470 MotionRotate::MotionRotate(MotionMain *plugin,
471         MotionWindow *gui, int x, int y)
472  : BC_CheckBox(x, y, plugin->config.rotate, _("Track rotation"))
473 {
474         this->plugin = plugin;
475         this->gui = gui;
476 }
477
478 int MotionRotate::handle_event()
479 {
480         plugin->config.rotate = get_value();
481         plugin->send_configure_change();
482         return 1;
483 }
484
485
486 MotionBlockX::MotionBlockX(MotionMain *plugin,
487         MotionWindow *gui, int x, int y)
488  : BC_FPot(x, y, plugin->config.block_x, (float)0, (float)100)
489 {
490         this->plugin = plugin;
491         this->gui = gui;
492 }
493
494 int MotionBlockX::handle_event()
495 {
496         plugin->config.block_x = get_value();
497         gui->block_x_text->update((float)plugin->config.block_x);
498         plugin->send_configure_change();
499         return 1;
500 }
501
502
503 MotionBlockY::MotionBlockY(MotionMain *plugin,
504         MotionWindow *gui,
505         int x,
506         int y)
507  : BC_FPot(x,
508         y,
509         (float)plugin->config.block_y,
510         (float)0,
511         (float)100)
512 {
513         this->plugin = plugin;
514         this->gui = gui;
515 }
516
517 int MotionBlockY::handle_event()
518 {
519         plugin->config.block_y = get_value();
520         gui->block_y_text->update((float)plugin->config.block_y);
521         plugin->send_configure_change();
522         return 1;
523 }
524
525 MotionBlockXText::MotionBlockXText(MotionMain *plugin,
526         MotionWindow *gui, int x, int y)
527  : BC_TextBox(x, y, xS(75), 1, (float)plugin->config.block_x)
528 {
529         this->plugin = plugin;
530         this->gui = gui;
531         set_precision(4);
532 }
533
534 int MotionBlockXText::handle_event()
535 {
536         plugin->config.block_x = atof(get_text());
537         gui->block_x->update(plugin->config.block_x);
538         plugin->send_configure_change();
539         return 1;
540 }
541
542
543
544
545 MotionBlockYText::MotionBlockYText(MotionMain *plugin,
546         MotionWindow *gui, int x, int y)
547  : BC_TextBox(x, y, xS(75), 1, (float)plugin->config.block_y)
548 {
549         this->plugin = plugin;
550         this->gui = gui;
551         set_precision(4);
552 }
553
554 int MotionBlockYText::handle_event()
555 {
556         plugin->config.block_y = atof(get_text());
557         gui->block_y->update(plugin->config.block_y);
558         plugin->send_configure_change();
559         return 1;
560 }
561
562
563 MotionDrawVectors::MotionDrawVectors(MotionMain *plugin,
564         MotionWindow *gui, int x, int y)
565  : BC_CheckBox(x,
566         y,
567         plugin->config.draw_vectors,
568         _("Draw vectors"))
569 {
570         this->gui = gui;
571         this->plugin = plugin;
572 }
573
574 int MotionDrawVectors::handle_event()
575 {
576         plugin->config.draw_vectors = get_value();
577         plugin->send_configure_change();
578         return 1;
579 }
580
581
582 TrackSingleFrame::TrackSingleFrame(MotionMain *plugin,
583         MotionWindow *gui,
584         int x,
585         int y)
586  : BC_Radial(x,
587         y,
588         plugin->config.tracking_object == MotionScan::TRACK_SINGLE,
589         _("Track single frame"))
590 {
591         this->plugin = plugin;
592         this->gui = gui;
593 }
594
595 int TrackSingleFrame::handle_event()
596 {
597         plugin->config.tracking_object = MotionScan::TRACK_SINGLE;
598         gui->track_previous->update(0);
599         gui->previous_same->update(0);
600         gui->track_frame_number->enable();
601         plugin->send_configure_change();
602         return 1;
603 }
604
605 TrackFrameNumber::TrackFrameNumber(MotionMain *plugin,
606         MotionWindow *gui,
607         int x,
608         int y)
609  : BC_TextBox(x, y, xS(100), 1, plugin->config.track_frame)
610 {
611         this->plugin = plugin;
612         this->gui = gui;
613 }
614
615 int TrackFrameNumber::handle_event()
616 {
617         plugin->config.track_frame = atol(get_text());
618         plugin->send_configure_change();
619         return 1;
620 }
621
622
623 TrackPreviousFrame::TrackPreviousFrame(MotionMain *plugin,
624         MotionWindow *gui,
625         int x,
626         int y)
627  : BC_Radial(x,
628         y,
629         plugin->config.tracking_object == MotionScan::TRACK_PREVIOUS,
630         _("Track previous frame"))
631 {
632         this->plugin = plugin;
633         this->gui = gui;
634 }
635 int TrackPreviousFrame::handle_event()
636 {
637         plugin->config.tracking_object = MotionScan::TRACK_PREVIOUS;
638         gui->track_single->update(0);
639         gui->previous_same->update(0);
640         gui->track_frame_number->disable();
641         plugin->send_configure_change();
642         return 1;
643 }
644
645
646 PreviousFrameSameBlock::PreviousFrameSameBlock(MotionMain *plugin,
647         MotionWindow *gui,
648         int x,
649         int y)
650  : BC_Radial(x,
651         y,
652         plugin->config.tracking_object == MotionScan::PREVIOUS_SAME_BLOCK,
653         _("Previous frame same block"))
654 {
655         this->plugin = plugin;
656         this->gui = gui;
657 }
658 int PreviousFrameSameBlock::handle_event()
659 {
660         plugin->config.tracking_object = MotionScan::PREVIOUS_SAME_BLOCK;
661         gui->track_single->update(0);
662         gui->track_previous->update(0);
663         gui->track_frame_number->disable();
664         plugin->send_configure_change();
665         return 1;
666 }
667
668
669 MasterLayer::MasterLayer(MotionMain *plugin, MotionWindow *gui, int x, int y)
670  : BC_PopupMenu(x,
671         y,
672         calculate_w(gui),
673         to_text(plugin->config.bottom_is_master))
674 {
675         this->plugin = plugin;
676         this->gui = gui;
677 }
678
679 int MasterLayer::handle_event()
680 {
681         plugin->config.bottom_is_master = from_text(get_text());
682         plugin->send_configure_change();
683         return 1;
684 }
685
686 void MasterLayer::create_objects()
687 {
688         add_item(new BC_MenuItem(to_text(0)));
689         add_item(new BC_MenuItem(to_text(1)));
690 }
691
692 int MasterLayer::from_text(char *text)
693 {
694         if(!strcmp(text, _("Top"))) return 0;
695         return 1;
696 }
697
698 char* MasterLayer::to_text(int mode)
699 {
700         return mode ? _("Bottom") : _("Top");
701 }
702
703 int MasterLayer::calculate_w(MotionWindow *gui)
704 {
705         int result = 0;
706         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0)));
707         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(1)));
708         return result + xS(80);
709 }
710
711
712 ActionType::ActionType(MotionMain *plugin, MotionWindow *gui, int x, int y)
713  : BC_PopupMenu(x,
714         y,
715         calculate_w(gui),
716         to_text(plugin->config.action_type))
717 {
718         this->plugin = plugin;
719         this->gui = gui;
720 }
721
722 int ActionType::handle_event()
723 {
724         plugin->config.action_type = from_text(get_text());
725         plugin->send_configure_change();
726         return 1;
727 }
728
729 void ActionType::create_objects()
730 {
731         add_item(new BC_MenuItem(to_text(MotionScan::TRACK)));
732         add_item(new BC_MenuItem(to_text(MotionScan::TRACK_PIXEL)));
733         add_item(new BC_MenuItem(to_text(MotionScan::STABILIZE)));
734         add_item(new BC_MenuItem(to_text(MotionScan::STABILIZE_PIXEL)));
735         add_item(new BC_MenuItem(to_text(MotionScan::NOTHING)));
736 }
737
738 int ActionType::from_text(char *text)
739 {
740         if(!strcmp(text, _("Track Subpixel"))) return MotionScan::TRACK;
741         if(!strcmp(text, _("Track Pixel"))) return MotionScan::TRACK_PIXEL;
742         if(!strcmp(text, _("Stabilize Subpixel"))) return MotionScan::STABILIZE;
743         if(!strcmp(text, _("Stabilize Pixel"))) return MotionScan::STABILIZE_PIXEL;
744         //if(!strcmp(text, _("Do Nothing"))) return MotionScan::NOTHING;
745         return MotionScan::NOTHING;
746 }
747
748 char* ActionType::to_text(int mode)
749 {
750         switch(mode)
751         {
752                 case MotionScan::TRACK:
753                         return _("Track Subpixel");
754                 case MotionScan::TRACK_PIXEL:
755                         return _("Track Pixel");
756                 case MotionScan::STABILIZE:
757                         return _("Stabilize Subpixel");
758                 case MotionScan::STABILIZE_PIXEL:
759                         return _("Stabilize Pixel");
760                 default:
761                 case MotionScan::NOTHING:
762                         return _("Do Nothing");
763         }
764 }
765
766 int ActionType::calculate_w(MotionWindow *gui)
767 {
768         int result = 0;
769         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::TRACK)));
770         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::TRACK_PIXEL)));
771         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::STABILIZE)));
772         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::STABILIZE_PIXEL)));
773         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::NOTHING)));
774         return result + xS(80);
775 }
776
777
778 TrackingType::TrackingType(MotionMain *plugin, MotionWindow *gui, int x, int y)
779  : BC_PopupMenu(x,
780         y,
781         calculate_w(gui),
782         to_text(plugin->config.tracking_type))
783 {
784         this->plugin = plugin;
785         this->gui = gui;
786 }
787
788 int TrackingType::handle_event()
789 {
790         plugin->config.tracking_type = from_text(get_text());
791         plugin->send_configure_change();
792         return 1;
793 }
794
795 void TrackingType::create_objects()
796 {
797         add_item(new BC_MenuItem(to_text(MotionScan::SAVE)));
798         add_item(new BC_MenuItem(to_text(MotionScan::LOAD)));
799         add_item(new BC_MenuItem(to_text(MotionScan::CALCULATE)));
800         add_item(new BC_MenuItem(to_text(MotionScan::NO_CALCULATE)));
801 }
802
803 int TrackingType::from_text(char *text)
804 {
805         if(!strcmp(text, _("Save coords to tracking file"))) return MotionScan::SAVE;
806         if(!strcmp(text, _("Load coords from tracking file"))) return MotionScan::LOAD;
807         if(!strcmp(text, _("Recalculate"))) return MotionScan::CALCULATE;
808         //if(!strcmp(text, _("Don't Calculate"))) return MotionScan::NO_CALCULATE;
809         return MotionScan::NO_CALCULATE;
810 }
811
812 char* TrackingType::to_text(int mode)
813 {
814         switch(mode)
815         {
816                 case MotionScan::SAVE:          return _("Save coords to tracking file");
817                 case MotionScan::LOAD:          return _("Load coords from tracking file");
818                 case MotionScan::CALCULATE:     return _("Recalculate");
819                 default:
820                 case MotionScan::NO_CALCULATE:  return _("Don't Calculate");
821         }
822 }
823
824 int TrackingType::calculate_w(MotionWindow *gui)
825 {
826         int result = 0;
827         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::NO_CALCULATE)));
828         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::CALCULATE)));
829         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::SAVE)));
830         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::LOAD)));
831         return result + xS(80);
832 }
833
834
835 TrackDirection::TrackDirection(MotionMain *plugin, MotionWindow *gui, int x, int y)
836  : BC_PopupMenu(x,
837         y,
838         calculate_w(gui),
839         to_text(plugin->config.horizontal_only, plugin->config.vertical_only))
840 {
841         this->plugin = plugin;
842         this->gui = gui;
843 }
844
845 int TrackDirection::handle_event()
846 {
847         from_text(&plugin->config.horizontal_only, &plugin->config.vertical_only, get_text());
848         plugin->send_configure_change();
849         return 1;
850 }
851
852 void TrackDirection::create_objects()
853 {
854         add_item(new BC_MenuItem(to_text(1, 0)));
855         add_item(new BC_MenuItem(to_text(0, 1)));
856         add_item(new BC_MenuItem(to_text(0, 0)));
857 }
858
859 void TrackDirection::from_text(int *horizontal_only, int *vertical_only, char *text)
860 {
861         *horizontal_only = 0;
862         *vertical_only = 0;
863         if(!strcmp(text, to_text(1, 0))) *horizontal_only = 1;
864         if(!strcmp(text, to_text(0, 1))) *vertical_only = 1;
865 }
866
867 char* TrackDirection::to_text(int horizontal_only, int vertical_only)
868 {
869         if(horizontal_only) return _("Horizontal only");
870         if(vertical_only) return _("Vertical only");
871         return _("Both");
872 }
873
874 int TrackDirection::calculate_w(MotionWindow *gui)
875 {
876         int result = 0;
877         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(1, 0)));
878         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0, 1)));
879         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0, 0)));
880         return result + xS(80);
881 }
882