mod motion tracking file in motion/motion-cv
[goodguy/history.git] / cinelerra-5.1 / plugins / motion-cv / motionwindow-cv.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 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-cv.h"
29 #include "motionwindow-cv.h"
30 #include "mwindow.h"
31 #include "pluginserver.h"
32
33 MotionCVWindow::MotionCVWindow(MotionCVMain *plugin)
34  : PluginClientWindow(plugin, 815, 650, 815, 650, 0)
35 {
36         this->plugin = plugin;
37 }
38
39 MotionCVWindow::~MotionCVWindow()
40 {
41 }
42
43 void MotionCVWindow::create_objects()
44 {
45         int x1 = 10, x = 10, y = 10;
46         int x2 = 410;
47         BC_Title *title;
48
49         add_subwindow(global = new MotionCVGlobal(plugin, this, x1, y));
50         add_subwindow(rotate = new MotionCVRotate(plugin, this, x2, y));
51         y += 50;
52
53         add_subwindow(title = new BC_Title(x1, y,
54                 _("Translation search radius:\n(W/H Percent of image)")));
55         add_subwindow(global_range_w = new GlobalRange(plugin,
56                         x1 + title->get_w() + 10, y,
57                         &plugin->config.global_range_w));
58         add_subwindow(global_range_h = new GlobalRange(plugin,
59                         x1 + title->get_w() + 30 + global_range_w->get_w(), y,
60                         &plugin->config.global_range_h));
61
62         add_subwindow(title = new BC_Title(x2, y,
63                 _("Rotation search radius:\n(Degrees)")));
64         add_subwindow(rotation_range =
65                       new RotationRange(plugin, x2 + title->get_w() + 10, y));
66
67         y += 50;
68         add_subwindow(title = new BC_Title(x1, y,
69                 _("Translation block size:\n(W/H Percent of image)")));
70         add_subwindow(global_block_w = new BlockSize(plugin,
71                         x1 + title->get_w() + 10, y,
72                         &plugin->config.global_block_w));
73         add_subwindow(global_block_h = new BlockSize(plugin,
74                         x1 + title->get_w() + 30 + global_block_w->get_w(), y,
75                         &plugin->config.global_block_h));
76
77         add_subwindow(title = new BC_Title(x2, y,
78                 _("Rotation block size:\n(W/H Percent of image)")));
79         add_subwindow(rotation_block_w = new BlockSize(plugin,
80                         x2 + title->get_w() + 10, y,
81                         &plugin->config.rotation_block_w));
82         add_subwindow(rotation_block_h = new BlockSize(plugin,
83                         x2 + title->get_w() + 30 + rotation_block_w->get_w(), y,
84                         &plugin->config.rotation_block_h));
85
86         y += 50;
87         add_subwindow(title = new BC_Title(x1, y, _("Translation search steps:")));
88         add_subwindow(global_search_positions = new GlobalSearchPositions(plugin,
89                         x1 + title->get_w() + 10, y, 80));
90         global_search_positions->create_objects();
91
92         add_subwindow(title = new BC_Title(x2, y, _("Rotation search steps:")));
93         add_subwindow(rotation_search_positions = new RotationSearchPositions(plugin,
94                         x2 + title->get_w() + 10, y, 80));
95         rotation_search_positions->create_objects();
96
97         y += 50;
98         add_subwindow(title = new BC_Title(x, y, _("Translation direction:")));
99         add_subwindow(mode3 = new Mode3(plugin,
100                         this, x + title->get_w() + 10, y));
101         mode3->create_objects();
102
103         y += 40;
104         add_subwindow(title = new BC_Title(x, y + 10, _("Block X:")));
105         add_subwindow(block_x = new MotionCVBlockX(plugin, this,
106                         x + title->get_w() + 10, y));
107         add_subwindow(block_x_text = new MotionCVBlockXText(plugin,
108                         this, x + title->get_w() + 10 + block_x->get_w() + 10, y + 10));
109
110         y += 40;
111         add_subwindow(title = new BC_Title(x, y + 10, _("Block Y:")));
112         add_subwindow(block_y = new MotionCVBlockY(plugin, this,
113                         x + title->get_w() + 10, y));
114         add_subwindow(block_y_text = new MotionCVBlockYText(plugin, this,
115                         x + title->get_w() + 10 + block_y->get_w() + 10, y + 10));
116
117         y += 50;
118         add_subwindow(title = new BC_Title(x, y + 10, _("Maximum absolute offset:")));
119         add_subwindow(magnitude = new MotionCVMagnitude(plugin,
120                         x + title->get_w() + 10, y));
121
122         y += 40;
123         add_subwindow(title = new BC_Title(x, y + 10, _("Settling speed:")));
124         add_subwindow(return_speed = new MotionCVReturnSpeed(plugin,
125                         x + title->get_w() + 10, y));
126
127         y += 40;
128         add_subwindow(vectors = new MotionCVDrawVectors(plugin, this, x, y));
129
130         add_subwindow(title = new BC_Title(x2, y, _("Tracking file:")));
131         add_subwindow(tracking_file = new MotionCVTrackingFile(plugin,
132                         plugin->config.  tracking_file, this,
133                         x2 + title->get_w() + 20, y));
134
135         y += 40;
136         x1 = x;  int y1 = y;
137         add_subwindow(track_single =
138                 new TrackSingleFrame(plugin, this, x1, y1));
139         add_subwindow(title =
140                 new BC_Title(x1 += track_single->get_w() + 20, y1, _("Frame number:")));
141         add_subwindow(track_frame_number =
142                 new TrackFrameNumber(plugin, this, x1 += title->get_w(), y1));
143         add_subwindow(addtrackedframeoffset =
144                 new AddTrackedFrameOffset(plugin, this, x1, y1+=track_frame_number->get_h()));
145         int pef = client->server->mwindow->edl->session->video_every_frame;
146         add_subwindow(pef_title = new BC_Title(x1, y1+=addtrackedframeoffset->get_h() + 5,
147                 !pef ?  _("For best results\n"
148                                 " Set: Play every frame\n"
149                                 " Preferences-> Playback-> Video Out") :
150                         _("Currently using: Play every frame"), MEDIUMFONT,
151                 !pef ? RED : GREEN));
152
153         y += 20;
154         add_subwindow(track_previous = new TrackPreviousFrame(plugin, this, x, y));
155         y += 20;
156         add_subwindow(previous_same = new PreviousFrameSameBlock(plugin, this, x, y));
157
158         y += 40;
159         //int y1 = y;
160         add_subwindow(title = new BC_Title(x, y, _("Master layer:")));
161         add_subwindow(master_layer = new MasterLayer(plugin, this,
162                         x + title->get_w() + 10, y));
163         master_layer->create_objects();
164         y += 30;
165
166         add_subwindow(title = new BC_Title(x, y, _("Action:")));
167         add_subwindow(mode1 = new Mode1(plugin, this,
168                         x + title->get_w() + 10, y));
169         mode1->create_objects();
170         y += 30;
171
172         add_subwindow(title = new BC_Title(x, y, _("Calculation:")));
173         add_subwindow(mode2 = new Mode2(plugin, this,
174                         x + title->get_w() + 10, y));
175         mode2->create_objects();
176
177         show_window(1);
178 }
179
180 void MotionCVWindow::update_mode()
181 {
182         global_range_w->update(plugin->config.global_range_w, MIN_RADIUS, MAX_RADIUS);
183         global_range_h->update(plugin->config.global_range_h, MIN_RADIUS, MAX_RADIUS);
184         rotation_range->update(plugin->config.rotation_range, MIN_ROTATION, MAX_ROTATION);
185         vectors->update(plugin->config.draw_vectors);
186         tracking_file->update(plugin->config.tracking_file);
187         global->update(plugin->config.global);
188         rotate->update(plugin->config.rotate);
189         addtrackedframeoffset->update(plugin->config.addtrackedframeoffset);
190 }
191
192 GlobalRange::GlobalRange(MotionCVMain *plugin, int x, int y, int *value)
193 :BC_IPot(x, y, (int64_t) * value, (int64_t) MIN_RADIUS, (int64_t) MAX_RADIUS)
194 {
195         this->plugin = plugin;
196         this->value = value;
197 }
198
199 int GlobalRange::handle_event()
200 {
201         *value = (int)get_value();
202         plugin->send_configure_change();
203         return 1;
204 }
205
206 RotationRange::RotationRange(MotionCVMain *plugin, int x, int y)
207  :
208 BC_IPot(x,
209     y, (int64_t) plugin->config.rotation_range,
210     (int64_t) MIN_ROTATION, (int64_t) MAX_ROTATION)
211 {
212         this->plugin = plugin;
213 }
214
215 int RotationRange::handle_event()
216 {
217         plugin->config.rotation_range = (int)get_value();
218         plugin->send_configure_change();
219         return 1;
220 }
221
222 BlockSize::BlockSize(MotionCVMain *plugin, int x, int y, int *value)
223  : BC_IPot(x, y, (int64_t) * value, (int64_t) MIN_BLOCK, (int64_t) MAX_BLOCK)
224 {
225         this->plugin = plugin;
226         this->value = value;
227 }
228
229 int BlockSize::handle_event()
230 {
231         *value = (int)get_value();
232         plugin->send_configure_change();
233         return 1;
234 }
235
236 GlobalSearchPositions::GlobalSearchPositions(MotionCVMain *plugin,
237                                              int x, int y, int w)
238  : BC_PopupMenu(x, y, w, "", 1)
239 {
240         this->plugin = plugin;
241 }
242
243 void GlobalSearchPositions::create_objects()
244 {
245         add_item(new BC_MenuItem("64"));
246         add_item(new BC_MenuItem("128"));
247         add_item(new BC_MenuItem("256"));
248         add_item(new BC_MenuItem("512"));
249         add_item(new BC_MenuItem("1024"));
250         add_item(new BC_MenuItem("2048"));
251         add_item(new BC_MenuItem("4096"));
252         add_item(new BC_MenuItem("8192"));
253         add_item(new BC_MenuItem("16384"));
254         add_item(new BC_MenuItem("32768"));
255         add_item(new BC_MenuItem("65536"));
256         add_item(new BC_MenuItem("131072"));
257         char string[BCTEXTLEN];
258         sprintf(string, "%d", plugin->config.global_positions);
259         set_text(string);
260 }
261
262 int GlobalSearchPositions::handle_event()
263 {
264         plugin->config.global_positions = atoi(get_text());
265         plugin->send_configure_change();
266         return 1;
267 }
268
269 RotationSearchPositions::RotationSearchPositions(MotionCVMain *plugin,
270                 int x, int y, int w)
271  : BC_PopupMenu(x, y, w, "", 1)
272 {
273         this->plugin = plugin;
274 }
275
276 void RotationSearchPositions::create_objects()
277 {
278         add_item(new BC_MenuItem("4"));
279         add_item(new BC_MenuItem("8"));
280         add_item(new BC_MenuItem("16"));
281         add_item(new BC_MenuItem("32"));
282         char string[BCTEXTLEN];
283         sprintf(string, "%d", plugin->config.rotate_positions);
284         set_text(string);
285 }
286
287 int RotationSearchPositions::handle_event()
288 {
289         plugin->config.rotate_positions = atoi(get_text());
290         plugin->send_configure_change();
291         return 1;
292 }
293
294 MotionCVMagnitude::MotionCVMagnitude(MotionCVMain *plugin, int x, int y)
295  : BC_IPot(x, y, (int64_t) plugin->config.magnitude, (int64_t) 0, (int64_t) 100)
296 {
297         this->plugin = plugin;
298 }
299
300 int MotionCVMagnitude::handle_event()
301 {
302         plugin->config.magnitude = (int)get_value();
303         plugin->send_configure_change();
304         return 1;
305 }
306
307 MotionCVReturnSpeed::MotionCVReturnSpeed(MotionCVMain *plugin, int x, int y)
308  : BC_IPot(x, y, (int64_t) plugin->config.return_speed, (int64_t) 0, (int64_t) 100)
309 {
310         this->plugin = plugin;
311 }
312
313 int MotionCVReturnSpeed::handle_event()
314 {
315         plugin->config.return_speed = (int)get_value();
316         plugin->send_configure_change();
317         return 1;
318 }
319
320 AddTrackedFrameOffset::AddTrackedFrameOffset(MotionCVMain *plugin,
321                 MotionCVWindow *gui, int x, int y)
322  : BC_CheckBox(x, y, plugin->config.addtrackedframeoffset,
323         _("Add (loaded) offset from tracked frame"))
324 {
325         this->plugin = plugin;
326         this->gui = gui;
327 }
328
329 int AddTrackedFrameOffset::handle_event()
330 {
331         plugin->config.addtrackedframeoffset = get_value();
332         plugin->send_configure_change();
333         return 1;
334 }
335
336 MotionCVTrackingFile::MotionCVTrackingFile(MotionCVMain *plugin,
337                 const char *filename, MotionCVWindow *gui, int x, int y)
338  : BC_TextBox(x, y, 250, 1, filename)
339 {
340         this->plugin = plugin;
341         this->gui = gui;
342 };
343
344 int MotionCVTrackingFile::handle_event()
345 {
346         strcpy(plugin->config.tracking_file, get_text());
347         plugin->send_configure_change();
348         return 1;
349 }
350
351 MotionCVGlobal::MotionCVGlobal(MotionCVMain *plugin,
352                 MotionCVWindow *gui, int x, int y)
353  :BC_CheckBox(x, y, plugin->config.global, _("Track translation"))
354 {
355         this->plugin = plugin;
356         this->gui = gui;
357 }
358
359 int MotionCVGlobal::handle_event()
360 {
361         plugin->config.global = get_value();
362         plugin->send_configure_change();
363         return 1;
364 }
365
366 MotionCVRotate::MotionCVRotate(MotionCVMain *plugin,
367                 MotionCVWindow *gui, int x, int y)
368  : BC_CheckBox(x, y, plugin->config.rotate, _("Track rotation"))
369 {
370         this->plugin = plugin;
371         this->gui = gui;
372 }
373
374 int MotionCVRotate::handle_event()
375 {
376         plugin->config.rotate = get_value();
377         plugin->send_configure_change();
378         return 1;
379 }
380
381 MotionCVBlockX::MotionCVBlockX(MotionCVMain *plugin,
382                 MotionCVWindow *gui, int x, int y)
383  : BC_FPot(x, y, plugin->config.block_x, (float)0, (float)100)
384 {
385         this->plugin = plugin;
386         this->gui = gui;
387 }
388
389 int MotionCVBlockX::handle_event()
390 {
391         plugin->config.block_x = get_value();
392         gui->block_x_text->update((float)plugin->config.block_x);
393         plugin->send_configure_change();
394         return 1;
395 }
396
397 MotionCVBlockY::MotionCVBlockY(MotionCVMain *plugin,
398                 MotionCVWindow *gui, int x, int y)
399  : BC_FPot(x, y, (float)plugin->config.block_y, (float)0, (float)100)
400 {
401         this->plugin = plugin;
402         this->gui = gui;
403 }
404
405 int MotionCVBlockY::handle_event()
406 {
407         plugin->config.block_y = get_value();
408         gui->block_y_text->update((float)plugin->config.block_y);
409         plugin->send_configure_change();
410         return 1;
411 }
412
413 MotionCVBlockXText::MotionCVBlockXText(MotionCVMain *plugin,
414                 MotionCVWindow *gui, int x, int y)
415  : BC_TextBox(x, y, 75, 1, (float)plugin->config.block_x)
416 {
417         this->plugin = plugin;
418         this->gui = gui;
419         set_precision(4);
420 }
421
422 int MotionCVBlockXText::handle_event()
423 {
424         plugin->config.block_x = atof(get_text());
425         gui->block_x->update(plugin->config.block_x);
426         plugin->send_configure_change();
427         return 1;
428 }
429
430 MotionCVBlockYText::MotionCVBlockYText(MotionCVMain *plugin,
431                 MotionCVWindow *gui, int x, int y)
432  : BC_TextBox(x, y, 75, 1, (float)plugin->config.block_y)
433 {
434         this->plugin = plugin;
435         this->gui = gui;
436         set_precision(4);
437 }
438
439 int MotionCVBlockYText::handle_event()
440 {
441         plugin->config.block_y = atof(get_text());
442         gui->block_y->update(plugin->config.block_y);
443         plugin->send_configure_change();
444         return 1;
445 }
446
447 MotionCVDrawVectors::MotionCVDrawVectors(MotionCVMain *plugin,
448                 MotionCVWindow *gui, int x, int y)
449  : BC_CheckBox(x, y, plugin->config.draw_vectors, _("Draw vectors"))
450 {
451         this->gui = gui;
452         this->plugin = plugin;
453 }
454
455 int MotionCVDrawVectors::handle_event()
456 {
457         plugin->config.draw_vectors = get_value();
458         plugin->send_configure_change();
459         return 1;
460 }
461
462 TrackSingleFrame::TrackSingleFrame(MotionCVMain *plugin,
463                 MotionCVWindow *gui, int x, int y)
464  :
465 BC_Radial(x,
466       y, plugin->config.mode3 == MotionCVConfig::TRACK_SINGLE,
467       _("Track single frame"))
468 {
469         this->plugin = plugin;
470         this->gui = gui;
471 }
472
473 int TrackSingleFrame::handle_event()
474 {
475         plugin->config.mode3 = MotionCVConfig::TRACK_SINGLE;
476         gui->track_previous->update(0);
477         gui->previous_same->update(0);
478         gui->track_frame_number->enable();
479         plugin->send_configure_change();
480         return 1;
481 }
482
483 TrackFrameNumber::TrackFrameNumber(MotionCVMain *plugin,
484                 MotionCVWindow *gui, int x, int y)
485  : BC_TextBox(x, y, 100, 1, plugin->config.track_frame)
486 {
487         this->plugin = plugin;
488         this->gui = gui;
489         if( plugin->config.mode3 != MotionCVConfig::TRACK_SINGLE )
490                 disable();
491 }
492
493 int TrackFrameNumber::handle_event()
494 {
495         plugin->config.track_frame = atol(get_text());
496         plugin->send_configure_change();
497         return 1;
498 }
499
500 TrackPreviousFrame::TrackPreviousFrame(MotionCVMain *plugin,
501                 MotionCVWindow *gui, int x, int y)
502  :
503 BC_Radial(x,
504       y, plugin->config.mode3 == MotionCVConfig::TRACK_PREVIOUS,
505       _("Track previous frame"))
506 {
507         this->plugin = plugin;
508         this->gui = gui;
509 }
510
511 int TrackPreviousFrame::handle_event()
512 {
513         plugin->config.mode3 = MotionCVConfig::TRACK_PREVIOUS;
514         gui->track_single->update(0);
515         gui->previous_same->update(0);
516         gui->track_frame_number->disable();
517         plugin->send_configure_change();
518         return 1;
519 }
520
521 PreviousFrameSameBlock::PreviousFrameSameBlock(MotionCVMain *plugin,
522                 MotionCVWindow *gui, int x, int y)
523  :
524 BC_Radial(x,
525       y, plugin->config.mode3 == MotionCVConfig::PREVIOUS_SAME_BLOCK,
526       _("Previous frame same block"))
527 {
528         this->plugin = plugin;
529         this->gui = gui;
530 }
531
532 int PreviousFrameSameBlock::handle_event()
533 {
534         plugin->config.mode3 = MotionCVConfig::PREVIOUS_SAME_BLOCK;
535         gui->track_single->update(0);
536         gui->track_previous->update(0);
537         gui->track_frame_number->disable();
538         plugin->send_configure_change();
539         return 1;
540 }
541
542 MasterLayer::MasterLayer(MotionCVMain *plugin, MotionCVWindow *gui, int x,
543                          int y)
544  : BC_PopupMenu(x, y, calculate_w(gui),
545              to_text(plugin->config.bottom_is_master))
546 {
547         this->plugin = plugin;
548         this->gui = gui;
549 }
550
551 int MasterLayer::handle_event()
552 {
553         plugin->config.bottom_is_master = from_text(get_text());
554         plugin->send_configure_change();
555         return 1;
556 }
557
558 void MasterLayer::create_objects()
559 {
560         add_item(new BC_MenuItem(to_text(0)));
561         add_item(new BC_MenuItem(to_text(1)));
562 }
563
564 int MasterLayer::from_text(char *text)
565 {
566         if( !strcmp(text, _("Top")) ) return 0;
567         return 1;
568 }
569
570 const char *MasterLayer::to_text(int mode)
571 {
572         return mode ? _("Bottom") : _("Top");
573 }
574
575 int MasterLayer::calculate_w(MotionCVWindow *gui)
576 {
577         int result = 0;
578         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0)));
579         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(1)));
580         return result + 50;
581 }
582
583 Mode1::Mode1(MotionCVMain *plugin, MotionCVWindow *gui, int x, int y)
584  : BC_PopupMenu(x, y, calculate_w(gui), to_text(plugin->config.mode1))
585 {
586         this->plugin = plugin;
587         this->gui = gui;
588 }
589
590 int Mode1::handle_event()
591 {
592         plugin->config.mode1 = from_text(get_text());
593         plugin->send_configure_change();
594         return 1;
595 }
596
597 void Mode1::create_objects()
598 {
599         add_item(new BC_MenuItem(to_text(MotionCVConfig::TRACK)));
600         add_item(new BC_MenuItem(to_text(MotionCVConfig::TRACK_PIXEL)));
601         add_item(new BC_MenuItem(to_text(MotionCVConfig::STABILIZE)));
602         add_item(new BC_MenuItem(to_text(MotionCVConfig::STABILIZE_PIXEL)));
603         add_item(new BC_MenuItem(to_text(MotionCVConfig::NOTHING)));
604 }
605
606 int Mode1::from_text(char *text)
607 {
608         if( !strcmp(text, _("Track Subpixel")) ) return MotionCVConfig::TRACK;
609         if( !strcmp(text, _("Track Pixel")) ) return MotionCVConfig::TRACK_PIXEL;
610         if( !strcmp(text, _("Stabilize Subpixel")) ) return MotionCVConfig::STABILIZE;
611         if( !strcmp(text, _("Stabilize Pixel")) ) return MotionCVConfig::STABILIZE_PIXEL;
612         //if( !strcmp(text, _("Do Nothing")) ) return MotionCVConfig::NOTHING;
613         return MotionCVConfig::NOTHING;
614 }
615
616 const char *Mode1::to_text(int mode)
617 {
618         switch( mode ) {
619         case MotionCVConfig::TRACK: return _("Track Subpixel");
620         case MotionCVConfig::TRACK_PIXEL: return _("Track Pixel");
621         case MotionCVConfig::STABILIZE: return _("Stabilize Subpixel");
622         case MotionCVConfig::STABILIZE_PIXEL: return _("Stabilize Pixel");
623         case MotionCVConfig::NOTHING: return _("Do Nothing");
624         }
625         return "";
626 }
627
628 int Mode1::calculate_w(MotionCVWindow *gui)
629 {
630         int result = 0;
631         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::TRACK)));
632         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::TRACK_PIXEL)));
633         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::STABILIZE)));
634         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::STABILIZE_PIXEL)));
635         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::NOTHING)));
636         return result + 50;
637 }
638
639 Mode2::Mode2(MotionCVMain *plugin, MotionCVWindow *gui, int x, int y)
640  : BC_PopupMenu(x, y, calculate_w(gui), to_text(plugin->config.mode2))
641 {
642         this->plugin = plugin;
643         this->gui = gui;
644 }
645
646 int Mode2::handle_event()
647 {
648         plugin->config.mode2 = from_text(get_text());
649         plugin->send_configure_change();
650         return 1;
651 }
652
653 void Mode2::create_objects()
654 {
655         add_item(new BC_MenuItem(to_text(MotionCVConfig::SAVE)));
656         add_item(new BC_MenuItem(to_text(MotionCVConfig::LOAD)));
657         add_item(new BC_MenuItem(to_text(MotionCVConfig::RECALCULATE)));
658         add_item(new BC_MenuItem(to_text(MotionCVConfig::NO_CALCULATE)));
659 }
660
661 int Mode2::from_text(char *text)
662 {
663         if( !strcmp(text, _("Recalculate")) ) return MotionCVConfig::RECALCULATE;
664         if( !strcmp(text, _("Save coords to tracking file")) ) return MotionCVConfig::SAVE;
665         if( !strcmp(text, _("Load coords from tracking file")) ) return MotionCVConfig::LOAD;
666         //if( !strcmp(text, _("Don't Calculate")) ) return MotionCVConfig::NO_CALCULATE;
667         return MotionCVConfig::NO_CALCULATE;
668 }
669
670 const char *Mode2::to_text(int mode)
671 {
672         switch( mode ) {
673         case MotionCVConfig::NO_CALCULATE: return _("Don't Calculate");
674         case MotionCVConfig::RECALCULATE: return _("Recalculate");
675         case MotionCVConfig::SAVE: return _("Save coords to tracking file");
676         case MotionCVConfig::LOAD: return _("Load coords from tracking file");
677         }
678         return "";
679 }
680
681 int Mode2::calculate_w(MotionCVWindow *gui)
682 {
683         int result = 0;
684         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::NO_CALCULATE)));
685         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::RECALCULATE)));
686         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::SAVE)));
687         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::LOAD)));
688         return result + 50;
689 }
690
691 Mode3::Mode3(MotionCVMain *plugin, MotionCVWindow *gui, int x, int y)
692  :
693 BC_PopupMenu(x, y, calculate_w(gui),
694          to_text(plugin->config.horizontal_only, plugin->config.vertical_only))
695 {
696         this->plugin = plugin;
697         this->gui = gui;
698 }
699
700 int Mode3::handle_event()
701 {
702         from_text(&plugin->config.horizontal_only,
703                   &plugin->config.vertical_only, get_text());
704         plugin->send_configure_change();
705         return 1;
706 }
707
708 void Mode3::create_objects()
709 {
710         add_item(new BC_MenuItem(to_text(1, 0)));
711         add_item(new BC_MenuItem(to_text(0, 1)));
712         add_item(new BC_MenuItem(to_text(0, 0)));
713 }
714
715 void Mode3::from_text(int *horizontal_only, int *vertical_only, char *text)
716 {
717         *horizontal_only = 0;
718         *vertical_only = 0;
719         if( !strcmp(text, to_text(1, 0)) ) *horizontal_only = 1;
720         if( !strcmp(text, to_text(0, 1)) ) *vertical_only = 1;
721 }
722
723 const char *Mode3::to_text(int horizontal_only, int vertical_only)
724 {
725         if( horizontal_only ) return _("Horizontal only");
726         if( vertical_only ) return _("Vertical only");
727         return _("Both");
728 }
729
730 int Mode3::calculate_w(MotionCVWindow *gui)
731 {
732         int result = 0;
733         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(1, 0)));
734         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0, 1)));
735         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0, 0)));
736         return result + 50;
737 }
738
739