+}
+
+int CWindowMaskOnTrack::handle_event()
+{
+ CWindowMaskItem *track_item = 0;
+ int k = get_number(), track_id = -1;
+//printf("selected %d = %s\n", k, k<0 ? "()" : track_items[k]->get_text());
+ if( k >= 0 ) {
+ track_item = (CWindowMaskItem *)track_items[k];
+ Track *track = track_item ? mwindow->edl->tracks->get_track_by_id(track_item->id) : 0;
+ if( track && track->is_armed() ) track_id = track->get_id();
+ }
+ else
+ track_id = mwindow->cwindow->mask_track_id;
+ set_back_color(track_id >= 0 ?
+ gui->get_resources()->text_background :
+ gui->get_resources()->text_background_disarmed);
+ if( mwindow->cwindow->mask_track_id != track_id )
+ gui->mask_on_track->update(track_item ? track_item->get_text() : "");
+ mwindow->cwindow->mask_track_id = track_id;
+ mwindow->edl->local_session->solo_track_id = -1;
+ gui->mask_solo_track->update(0);
+ gui->update();
+ gui->update_preview(1);
+ return 1;
+}
+
+void CWindowMaskOnTrack::update_items()
+{
+ track_items.remove_all_objects();
+ int high_color = gui->get_resources()->button_highlighted;
+ for( Track *track=mwindow->edl->tracks->first; track; track=track->next ) {
+ if( track->data_type != TRACK_VIDEO ) continue;
+ MaskAutos *mask_autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
+ int color = !track->is_armed() ? RED : mask_autos->first ? high_color : -1;
+ MaskAuto *mask_auto = (MaskAuto*)mask_autos->default_auto;
+ for( int i=0; color<0 && i<mask_auto->masks.size(); ++i )
+ if( mask_auto->masks[i]->points.size() > 0 ) color = high_color;
+ track_items.append(new CWindowMaskItem(track->title, track->get_id(), color));
+ }
+ update_list(&track_items);
+}
+
+CWindowMaskTrackTumbler::CWindowMaskTrackTumbler(MWindow *mwindow, CWindowMaskGUI *gui,
+ int x, int y)
+ : BC_Tumbler(x, y)
+{
+ this->mwindow = mwindow;
+ this->gui = gui;
+}
+CWindowMaskTrackTumbler::~CWindowMaskTrackTumbler()
+{
+}
+
+int CWindowMaskTrackTumbler::handle_up_event()
+{
+ return do_event(1);
+}
+
+int CWindowMaskTrackTumbler::handle_down_event()
+{
+ return do_event(-1);
+}
+
+int CWindowMaskTrackTumbler::do_event(int dir)
+{
+ CWindowMaskItem *track_item = 0;
+ CWindowMaskItem **items = (CWindowMaskItem**)&gui->mask_on_track->track_items[0];
+ int n = gui->mask_on_track->track_items.size();
+ int id = mwindow->cwindow->mask_track_id;
+ if( n > 0 ) {
+ int k = n;
+ while( --k >= 0 && items[k]->id != id );
+ if( k >= 0 ) {
+ k += dir;
+ bclamp(k, 0, n-1);
+ track_item = items[k];
+ }
+ else
+ track_item = items[0];
+ }
+ Track *track = track_item ? mwindow->edl->tracks->get_track_by_id(track_item->id) : 0;
+ int track_id = track_item && track && track->is_armed() ? track_item->id : -1;
+ gui->mask_on_track->set_back_color(track_id >= 0 ?
+ gui->get_resources()->text_background :
+ gui->get_resources()->text_background_disarmed);
+ gui->mask_on_track->update(track_item ? track_item->get_text() : "");
+ mwindow->cwindow->mask_track_id = track_item ? track_item->id : -1;
+ mwindow->edl->local_session->solo_track_id = -1;
+ gui->mask_solo_track->update(0);
+ gui->update();
+ gui->update_preview(1);
+ return 1;
+}
+
+
+CWindowMaskName::CWindowMaskName(MWindow *mwindow, CWindowMaskGUI *gui,
+ int x, int y, const char *text)
+ : BC_PopupTextBox(gui, 0, text, x, y, xS(100), yS(160))
+{
+ this->mwindow = mwindow;
+ this->gui = gui;
+}
+
+CWindowMaskName::~CWindowMaskName()
+{
+}
+
+int CWindowMaskName::handle_event()
+{
+ Track *track;
+ MaskAutos *autos;
+ MaskAuto *keyframe;
+ SubMask *mask;
+ MaskPoint *point;
+//printf("CWindowMaskGUI::update 1\n");
+ gui->get_keyframe(track, autos, keyframe, mask, point, 0);
+ if( track ) {
+ int k = get_number();
+ if( k < 0 ) k = mwindow->edl->session->cwindow_mask;
+ else mwindow->edl->session->cwindow_mask = k;
+ if( k >= 0 && k < mask_items.size() ) {
+ mask_items[k]->set_text(get_text());
+ update_list(&mask_items);
+ }
+#ifdef USE_KEYFRAME_SPANNING
+ MaskAuto temp_keyframe(mwindow->edl, autos);
+ temp_keyframe.copy_data(keyframe);
+ SubMask *submask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
+ memset(submask->name, 0, sizeof(submask->name));
+ strncpy(submask->name, get_text(), sizeof(submask->name)-1);
+ ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->update_parameter(&temp_keyframe);
+#else
+ for(MaskAuto *current = (MaskAuto*)autos->default_auto; current; ) {
+ SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
+ memset(submask->name, 0, sizeof(submask->name));
+ strncpy(submask->name, get_text(), sizeof(submask->name)-1);
+ current = current == (MaskAuto*)autos->default_auto ?
+ (MaskAuto*)autos->first : (MaskAuto*)NEXT;
+ }
+#endif
+ gui->update();
+ gui->update_preview();
+ }
+ return 1;
+}
+
+void CWindowMaskName::update_items(MaskAuto *keyframe)
+{
+ mask_items.remove_all_objects();
+ int sz = !keyframe ? 0 : keyframe->masks.size();
+ for( int i=0; i<SUBMASKS; ++i ) {
+ char text[BCSTRLEN]; memset(text, 0, sizeof(text));
+ if( i < sz ) {
+ SubMask *sub_mask = keyframe->masks.get(i);
+ strncpy(text, sub_mask->name, sizeof(text)-1);
+ }
+ else
+ sprintf(text, "%d", i);
+ mask_items.append(new CWindowMaskItem(text));
+ }
+ update_list(&mask_items);
+}
+
+
+CWindowMaskButton::CWindowMaskButton(MWindow *mwindow, CWindowMaskGUI *gui,
+ int x, int y, int no, int v)
+ : BC_CheckBox(x, y, v)
+{
+ this->mwindow = mwindow;
+ this->gui = gui;
+ this->no = no;
+}
+
+CWindowMaskButton::~CWindowMaskButton()
+{
+}
+
+int CWindowMaskButton::handle_event()
+{
+ mwindow->edl->session->cwindow_mask = no;
+ gui->mask_name->update(gui->mask_name->mask_items[no]->get_text());
+ gui->update();
+ gui->update_preview();
+ return 1;
+}
+
+CWindowMaskThumbler::CWindowMaskThumbler(MWindow *mwindow, CWindowMaskGUI *gui,
+ int x, int y)
+ : BC_Tumbler(x, y)
+{
+ this->mwindow = mwindow;
+ this->gui = gui;
+}
+
+CWindowMaskThumbler::~CWindowMaskThumbler()
+{
+}
+
+int CWindowMaskThumbler::handle_up_event()
+{
+ return do_event(1);
+}
+
+int CWindowMaskThumbler::handle_down_event()
+{
+ return do_event(-1);
+}
+
+int CWindowMaskThumbler::do_event(int dir)
+{
+ int k = mwindow->edl->session->cwindow_mask;
+ if( (k+=dir) >= SUBMASKS ) k = 0;
+ else if( k < 0 ) k = SUBMASKS-1;
+ mwindow->edl->session->cwindow_mask = k;
+ gui->mask_name->update(gui->mask_name->mask_items[k]->get_text());
+ gui->update();
+ gui->update_preview();
+ return 1;
+}
+
+CWindowMaskEnable::CWindowMaskEnable(MWindow *mwindow, CWindowMaskGUI *gui,
+ int x, int y, int no, int v)
+ : BC_CheckBox(x, y, v)
+{
+ this->mwindow = mwindow;
+ this->gui = gui;
+ this->no = no;
+}
+
+CWindowMaskEnable::~CWindowMaskEnable()
+{
+}
+
+int CWindowMaskEnable::handle_event()
+{
+ Track *track = mwindow->cwindow->calculate_mask_track();
+ if( track ) {
+ mwindow->undo->update_undo_before(_("mask enable"), this);
+ int bit = 1 << no;
+ if( get_value() )
+ track->masks |= bit;
+ else
+ track->masks &= ~bit;
+ gui->update();
+ gui->update_preview(1);
+ mwindow->undo->update_undo_after(_("mask enable"), LOAD_PATCHES);
+ }
+ return 1;
+}
+
+CWindowMaskUnclear::CWindowMaskUnclear(MWindow *mwindow,
+ CWindowMaskGUI *gui, int x, int y)
+ : BC_Button(x, y, mwindow->theme->get_image_set("unclear_button"))
+{
+ this->mwindow = mwindow;
+ this->gui = gui;
+ set_tooltip(_("Show/Hide mask"));
+}
+
+int CWindowMaskUnclear::handle_event()
+{
+ Track *track = mwindow->cwindow->calculate_mask_track();
+ if( track ) {
+ mwindow->undo->update_undo_before(_("mask enables"), this);
+ int m = (1<<SUBMASKS)-1;
+ if( track->masks == m )
+ track->masks = 0;
+ else
+ track->masks = m;
+ for( int i=0; i<SUBMASKS; ++i )
+ gui->mask_enables[i]->update((track->masks>>i) & 1);
+ gui->update_preview(1);
+ mwindow->undo->update_undo_after(_("mask enables"), LOAD_PATCHES);
+ }
+ return 1;
+}
+
+CWindowMaskSoloTrack::CWindowMaskSoloTrack(MWindow *mwindow,
+ CWindowMaskGUI *gui, int x, int y, int v)
+ : BC_CheckBox(x, y, v, _("Solo"))
+{
+ this->mwindow = mwindow;
+ this->gui = gui;
+ set_tooltip(_("Solo video track"));
+}
+
+int CWindowMaskSoloTrack::handle_event()
+{
+ mwindow->edl->local_session->solo_track_id =
+ get_value() ? mwindow->cwindow->mask_track_id : -1;
+ gui->update_preview(1);
+ return 1;
+}
+
+int CWindowMaskSoloTrack::calculate_w(BC_WindowBase *gui)
+{
+ int w = 0, h = 0;
+ calculate_extents(gui, &w, &h, _("Solo"));
+ return w;
+}
+
+CWindowMaskDelMask::CWindowMaskDelMask(MWindow *mwindow,
+ CWindowMaskGUI *gui, int x, int y)
+ : BC_GenericButton(x, y, _("Delete"))
+{
+ this->mwindow = mwindow;
+ this->gui = gui;
+ set_tooltip(_("Delete mask"));
+}
+
+int CWindowMaskDelMask::handle_event()
+{
+ MaskAutos *autos;
+ MaskAuto *keyframe;
+ Track *track;
+ MaskPoint *point;
+ SubMask *mask;
+ int total_points;