add BC_SCALE env var for hi def monitors, cleanup theme data
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / cwindowgui.C
index 2cfb5da53ffaa2f22a0ccee17721180b2733820e..13ac058bbfe60677e242d9337030a106907fb786 100644 (file)
@@ -81,7 +81,7 @@ CWindowGUI::CWindowGUI(MWindow *mwindow, CWindow *cwindow)
        mwindow->session->cwindow_y,
        mwindow->session->cwindow_w,
        mwindow->session->cwindow_h,
-       100, 100, 1, 1, 1,
+       xS(100), yS(100), 1, 1, 1,
        BC_WindowBase::get_resources()->bg_color,
        mwindow->get_cwindow_display())
 {
@@ -878,6 +878,7 @@ void panel_btn(fit_selection,(), fit_selection())
 void panel_btn(fit_autos,(int all), fit_autos(all))
 void panel_btn(set_editing_mode,(int mode), set_editing_mode(mode))
 void panel_btn(set_auto_keyframes,(int v), set_auto_keyframes(v))
+void panel_btn(set_span_keyframes,(int v), set_span_keyframes(v))
 void panel_btn(set_labels_follow_edits,(int v), set_labels_follow_edits(v))
 
 
@@ -945,14 +946,7 @@ int CWindowZoom::handle_event()
 
 #ifdef USE_SLIDER
 CWindowSlider::CWindowSlider(MWindow *mwindow, CWindow *cwindow, int x, int y, int pixels)
- : BC_PercentageSlider(x,
-                       y,
-                       0,
-                       pixels,
-                       pixels,
-                       0,
-                       1,
-                       0)
+ : BC_PercentageSlider(x, y, 0, pixels, pixels, 0, 1, 0)
 {
        this->mwindow = mwindow;
        this->cwindow = cwindow;
@@ -1035,15 +1029,10 @@ void CWindowTransport::goto_end()
 
 
 CWindowCanvas::CWindowCanvas(MWindow *mwindow, CWindowGUI *gui)
- : Canvas(mwindow,
-       gui,
-       mwindow->theme->ccanvas_x,
-       mwindow->theme->ccanvas_y,
-       mwindow->theme->ccanvas_w,
-       mwindow->theme->ccanvas_h,
-       0,
-       0,
-       mwindow->edl->session->cwindow_scrollbars)
+ : Canvas(mwindow, gui,
+       mwindow->theme->ccanvas_x, mwindow->theme->ccanvas_y,
+       mwindow->theme->ccanvas_w, mwindow->theme->ccanvas_h,
+       0, 0, mwindow->edl->session->cwindow_scrollbars)
 {
        this->mwindow = mwindow;
        this->gui = gui;
@@ -1131,8 +1120,8 @@ void CWindowCanvas::draw_refresh(int flush)
 //printf("CWindowCanvas::draw_refresh 10\n");
 }
 
-#define CROPHANDLE_W 10
-#define CROPHANDLE_H 10
+#define CROPHANDLE_W xS(10)
+#define CROPHANDLE_H yS(10)
 
 void CWindowCanvas::draw_crophandle(int x, int y)
 {
@@ -1140,20 +1129,18 @@ void CWindowCanvas::draw_crophandle(int x, int y)
 }
 
 
-#define CONTROL_W 10
-#define CONTROL_H 10
-#define FIRST_CONTROL_W 20
-#define FIRST_CONTROL_H 20
+#define CONTROL_W xS(10)
+#define CONTROL_H yS(10)
+#define FIRST_CONTROL_W xS(20)
+#define FIRST_CONTROL_H yS(20)
 #undef BC_INFINITY
 #define BC_INFINITY 65536
 
-#define RULERHANDLE_W 16
-#define RULERHANDLE_H 16
+#define RULERHANDLE_W xS(16)
+#define RULERHANDLE_H yS(16)
 
-int CWindowCanvas::do_ruler(int draw,
-       int motion,
-       int button_press,
-       int button_release)
+int CWindowCanvas::do_ruler(int draw, int motion,
+               int button_press, int button_release)
 {
        int result = 0;
        float x1 = mwindow->edl->session->ruler_x1;
@@ -1264,9 +1251,7 @@ int CWindowCanvas::do_ruler(int draw,
                                        {
                                                double angle_value = fabs(atan((mwindow->edl->session->ruler_y2 - mwindow->edl->session->ruler_y1) /
                                                        (mwindow->edl->session->ruler_x2 - mwindow->edl->session->ruler_x1)) *
-                                                       360 /
-                                                       2 /
-                                                       M_PI);
+                                                       360 / 2 / M_PI);
                                                double distance_value =
                                                        sqrt(SQR(mwindow->edl->session->ruler_x2 - mwindow->edl->session->ruler_x1) +
                                                        SQR(mwindow->edl->session->ruler_y2 - mwindow->edl->session->ruler_y1));
@@ -1314,9 +1299,7 @@ int CWindowCanvas::do_ruler(int draw,
                                        {
                                                double angle_value = fabs(atan((mwindow->edl->session->ruler_y2 - mwindow->edl->session->ruler_y1) /
                                                        (mwindow->edl->session->ruler_x2 - mwindow->edl->session->ruler_x1)) *
-                                                       360 /
-                                                       2 /
-                                                       M_PI);
+                                                       360 / 2 / M_PI);
                                                double distance_value =
                                                        sqrt(SQR(mwindow->edl->session->ruler_x2 - mwindow->edl->session->ruler_x1) +
                                                        SQR(mwindow->edl->session->ruler_y2 - mwindow->edl->session->ruler_y1));
@@ -1454,8 +1437,8 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
        Auto *prev_auto = 0;
        mask_autos->get_prev_auto(position, PLAY_FORWARD, (Auto *&)prev_auto, 1);
        MaskAuto *prev_mask = (MaskAuto *)prev_auto;
-       ArrayList<MaskPoint*> points;
-
+       MaskPoints points;
+       int update_points = 1;
 // Determine the points based on whether
 // new keyframes will be generated or drawing is performed.
 // If keyframe generation occurs, use the interpolated mask.
@@ -1755,6 +1738,8 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
                if( draw && mask_gui && mask_gui->focused ) {
                        float fx = atof(mask_gui->focus_x->get_text());
                        float fy = atof(mask_gui->focus_y->get_text());
+                       fx = (fx - half_track_w) * projector_z + projector_x;
+                       fy = (fy - half_track_h) * projector_z + projector_y;
                        output_to_canvas(mwindow->edl, 0, fx, fy);
                        float r = bmax(cvs_win->get_w(), cvs_win->get_h());
                        float d = 0.005*r;
@@ -1784,6 +1769,8 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
                        cx /= n;  cy /= n;
                        if( !mask_gui->focused )
                                mask_gui->set_focused(0, cx, cy);
+                       cx = (cx - half_track_w) * projector_z + projector_x;
+                       cy = (cy - half_track_h) * projector_z + projector_y;
                        output_to_canvas(mwindow->edl, 0, cx, cy);
                        float r = bmax(cvs_win->get_w(), cvs_win->get_h());
                        float d = 0.007*r;
@@ -1808,15 +1795,13 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
 // Make copy of current parameters in local keyframe
                        gui->mask_keyframe =
                                (MaskAuto*)gui->cwindow->calculate_affected_auto(
-                                       mask_autos,
-                                       0);
+                                       mask_autos, 0);
                        gui->orig_mask_keyframe->copy_data(gui->mask_keyframe);
 #else
 
                        gui->mask_keyframe =
                                (MaskAuto*)gui->cwindow->calculate_affected_auto(
-                                       mask_autos,
-                                       1);
+                                       mask_autos, 1);
 #endif
                }
                SubMask *mask = gui->mask_keyframe->get_submask(mwindow->edl->session->cwindow_mask);
@@ -2002,10 +1987,10 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
 
        if(button_press && result) {
 #ifdef USE_KEYFRAME_SPANNING
-               ArrayList<MaskPoint*> &mask_points = points;
+               MaskPoints &mask_points = points;
 #else
                SubMask *mask = gui->mask_keyframe->get_submask(mwindow->edl->session->cwindow_mask);
-               ArrayList<MaskPoint*> &mask_points = mask->points;
+               MaskPoints &mask_points = mask->points;
 #endif
                int k = gui->affected_point;
                if( k >= 0 && k < mask_points.size() ) {
@@ -2038,13 +2023,14 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
 //printf("CWindowCanvas::do_mask %d %d\n", __LINE__, gui->affected_point);
 
                SubMask *mask = gui->mask_keyframe->get_submask(mwindow->edl->session->cwindow_mask);
-               if( gui->affected_point >= 0 && gui->affected_point < mask->points.size() &&
-                       gui->current_operation != CWINDOW_NONE) {
+               if( mask && gui->affected_point >= 0 &&
+                   gui->affected_point < mask->points.size() &&
+                   gui->current_operation != CWINDOW_NONE ) {
 //                     mwindow->undo->update_undo_before(_("mask point"), this);
 #ifdef USE_KEYFRAME_SPANNING
-                       ArrayList<MaskPoint*> &mask_points = points;
+                       MaskPoints &mask_points = points;
 #else
-                       ArrayList<MaskPoint*> &mask_points = mask->points;
+                       MaskPoints &mask_points = mask->points;
 #endif
                        MaskPoint *point = mask_points.get(gui->affected_point);
 //                     canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
@@ -2075,14 +2061,33 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
                                point->control_y2 = mask_cursor_y - gui->y_origin + gui->control_out_y;
                                break;
 
-                       case CWINDOW_MASK_TRANSLATE:
-                               for(int i = 0; i < mask_points.size(); i++) {
-                                       mask_points.values[i]->x += mask_cursor_x - gui->x_origin;
-                                       mask_points.values[i]->y += mask_cursor_y - gui->y_origin;
+                       case CWINDOW_MASK_TRANSLATE: {
+                               if( !mask_gui ) break;
+                               int mode = mask_gui->scale_mode;
+                               MaskAuto *keyframe = gui->mask_keyframe;
+                               int gang = mask_gui->gang_focus->get_value();
+                               float dx = mask_cursor_x - gui->x_origin;
+                               float dy = mask_cursor_y - gui->y_origin;
+                               if( !dx && !dy ) break;
+                               int k = mwindow->edl->session->cwindow_mask;
+                               int n = gang ? keyframe->masks.size() : k+1;
+                               for( int j=gang? 0 : k; j<n; ++j ) {
+                                       if( !mask_gui->mask_enables[j]->get_value() ) continue;
+                                       SubMask *sub_mask = keyframe->get_submask(j);
+                                       if( !sub_mask ) continue;
+                                       MaskPoints &points = sub_mask->points;
+                                       for( int i=0; i<points.size(); ++i ) {
+                                               MaskPoint *point = points[i];
+                                               if( mode == MASK_SCALE_X || mode == MASK_SCALE_XY ) point->x += dx;
+                                               if( mode == MASK_SCALE_Y || mode == MASK_SCALE_XY ) point->y += dy;
+                                       }
                                }
                                gui->x_origin = mask_cursor_x;
                                gui->y_origin = mask_cursor_y;
-                               break;
+                               rerender = 1;
+                               redraw = 1;
+                               update_points = 0;
+                               break; }
                        case CWINDOW_MASK_ROTATE:
                                rotate = 1;
                        case CWINDOW_MASK_SCALE: {
@@ -2092,7 +2097,7 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
                                        cx = atof(mask_gui->focus_x->get_text());
                                        cy = atof(mask_gui->focus_y->get_text());
                                }
-                               else if( !gui->alt_down() ) {
+                               else if( !gui->ctrl_down() ) {
                                        cx = cy = 0;
                                        int n = mask_points.size();
                                        for( int i=0; i<n; ++i ) {
@@ -2104,36 +2109,58 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
                                }
                                gui->x_origin = cx;
                                gui->y_origin = cy;
+                               double accel =
+                                       gui->get_triple_click() ? 8. :
+                                       gui->get_double_click() ? 4. :
+                                       1.;
                                int button_no = get_buttonpress();
-                               double scale = button_no == WHEEL_UP ? 1.02 : 0.98;
-                               double theta = button_no == WHEEL_UP ? M_PI/360. : -M_PI/360.;
+                               double ds = accel/64., dt = accel*M_PI/360.;
+                               double scale = button_no == WHEEL_UP ? 1.+ds : 1.-ds;
+                               int mode = mask_gui->scale_mode;
+                               double xscale = !rotate && (mode == MASK_SCALE_X ||
+                                       mode == MASK_SCALE_XY ) ? scale : 1.;
+                               double yscale = !rotate && (mode == MASK_SCALE_Y ||
+                                       mode == MASK_SCALE_XY ) ? scale : 1.;
+                               double theta = button_no == WHEEL_UP ? dt : -dt;
+                               if( rotate ? theta==0 : scale==1 ) break;
                                float st = sin(theta), ct = cos(theta);
-                               for( int i=0; i<mask_points.size(); ++i ) {
-                                       MaskPoint *point = mask_points.values[i];
-                                       float px = point->x - gui->x_origin;
-                                       float py = point->y - gui->y_origin;
-                                       float nx = !rotate ? px*scale : px*ct + py*st;
-                                       float ny = !rotate ? py*scale : py*ct - px*st;
-                                       point->x = nx + gui->x_origin;
-                                       point->y = ny + gui->y_origin;
-                                       px = point->control_x1;  py = point->control_y1;
-                                       point->control_x1 = !rotate ? px*scale : px*ct + py*st;
-                                       point->control_y1 = !rotate ? py*scale : py*ct - px*st;
-                                       px = point->control_x2;  py = point->control_y2;
-                                       point->control_x2 = !rotate ? px*scale : px*ct + py*st;
-                                       point->control_y2 = !rotate ? py*scale : py*ct - px*st;
+                               MaskAuto *keyframe = gui->mask_keyframe;
+                               int gang = mask_gui->gang_focus->get_value();
+                               int k = mwindow->edl->session->cwindow_mask;
+                               int n = gang ? keyframe->masks.size() : k+1;
+                               for( int j=gang? 0 : k; j<n; ++j ) {
+                                       if( !mask_gui->mask_enables[j]->get_value() ) continue;
+                                       SubMask *sub_mask = keyframe->get_submask(j);
+                                       if( !sub_mask ) continue;
+                                       MaskPoints &points = sub_mask->points;
+                                       for( int i=0; i<points.size(); ++i ) {
+                                               MaskPoint *point = points[i];
+                                               float px = point->x - gui->x_origin;
+                                               float py = point->y - gui->y_origin;
+                                               float nx = !rotate ? px*xscale : px*ct + py*st;
+                                               float ny = !rotate ? py*yscale : py*ct - px*st;
+                                               point->x = nx + gui->x_origin;
+                                               point->y = ny + gui->y_origin;
+                                               px = point->control_x1;  py = point->control_y1;
+                                               point->control_x1 = !rotate ? px*xscale : px*ct + py*st;
+                                               point->control_y1 = !rotate ? py*yscale : py*ct - px*st;
+                                               px = point->control_x2;  py = point->control_y2;
+                                               point->control_x2 = !rotate ? px*xscale : px*ct + py*st;
+                                               point->control_y2 = !rotate ? py*yscale : py*ct - px*st;
+                                       }
                                }
                                rerender = 1;
                                redraw = 1;
+                               update_points = 0;
                                break; }
                        }
 
-                       if( !EQUIV(last_x, point->x) ||
+                       if( !(rerender && redraw) && (!EQUIV(last_x, point->x) ||
                                !EQUIV(last_y, point->y) ||
                                !EQUIV(last_control_x1, point->control_x1) ||
                                !EQUIV(last_control_y1, point->control_y1) ||
                                !EQUIV(last_control_x2, point->control_x2) ||
-                               !EQUIV(last_control_y2, point->control_y2)) {
+                               !EQUIV(last_control_y2, point->control_y2)) {
                                rerender = 1;
                                redraw = 1;
                        }
@@ -2192,22 +2219,61 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
                MaskAuto temp_keyframe(mwindow->edl, mask_autos);
                temp_keyframe.copy_data(gui->mask_keyframe);
 // Apply interpolated points back to keyframe
-               temp_keyframe.set_points(&points, mwindow->edl->session->cwindow_mask);
+               if( update_points )
+                       temp_keyframe.set_points(&points, mwindow->edl->session->cwindow_mask);
                gui->mask_keyframe->copy_data(gui->orig_mask_keyframe);
                mask_autos->update_parameter(&temp_keyframe);
        }
 #endif
-
-       points.remove_all_objects();
 //printf("CWindowCanvas::do_mask 20\n");
+
+       if( draw && draw_boundary && !draw_markers ) {
+               BC_WindowBase *cvs_win = get_canvas();
+               cvs_win->set_inverse();
+               cvs_win->set_color(RED+GREEN);
+               for( int k=0; k<SUBMASKS; ++k ) {
+                       if( k == mwindow->edl->session->cwindow_mask ) continue;
+                       points.remove_all_objects();
+                       if( use_interpolated )
+                               mask_autos->get_points(&points, k, position, PLAY_FORWARD);
+                       else
+                               prev_mask->get_points(&points, k);
+                       MaskEdge edge;
+                       edge.load(points, 0);
+                       for( int i=0; i<edge.size(); ++i ) {
+                               MaskCoord a = edge[i];
+                               MaskCoord b = i<edge.size()-1 ? edge[i+1] : edge[0];
+                               float ax = a.x, ay = a.y;
+                               float bx = b.x, by = b.y;
+                               output_to_canvas(mwindow->edl, 0, ax, ay);
+                               output_to_canvas(mwindow->edl, 0, bx, by);
+                               cvs_win->draw_line(ax,ay, bx,by);
+                       }
+               }
+       }
+
        return result;
 }
 
 int CWindowCanvas::do_mask_focus()
 {
-       CWindowMaskGUI *mask_gui = (CWindowMaskGUI*) gui->tool_panel->tool_gui;
+       Track *track = gui->cwindow->calculate_affected_track();
+       int64_t position = track->to_units(
+               mwindow->edl->local_session->get_selectionstart(1),
+               0);
+       float projector_x, projector_y, projector_z;
+       track->automation->get_projector(
+               &projector_x, &projector_y, &projector_z,
+               position, PLAY_FORWARD);
        float cx = get_cursor_x(), cy = get_cursor_y();
        canvas_to_output(mwindow->edl, 0, cx, cy);
+       projector_x += mwindow->edl->session->output_w / 2;
+       projector_y += mwindow->edl->session->output_h / 2;
+       float half_track_w = (float)track->track_w / 2;
+       float half_track_h = (float)track->track_h / 2;
+       cx = (cx - projector_x) / projector_z + half_track_w;
+       cy = (cy - projector_y) / projector_z + half_track_h;
+       CWindowMaskGUI *mask_gui = (CWindowMaskGUI*) gui->tool_panel->tool_gui;
        mask_gui->set_focused(1, cx, cy);
        return 1;
 }
@@ -3042,7 +3108,7 @@ int CWindowCanvas::test_bezier(int button_press,
                        float z_val = gui->affected_z->get_value();
 
                        if( gui->translating_zoom ) {
-                               float z = gui->center_z + (cursor_y - gui->y_origin) / 128;
+                               float z = gui->center_z + (cursor_y - gui->y_origin) / yS(128);
                                if( z < 0 ) z = 0;
                                if( !EQUIV(z_val, z) ) {
                                        rerender = 1;
@@ -3466,5 +3532,10 @@ int CWindowCanvas::get_cwindow_controls()
        return mwindow->session->cwindow_controls;
 }
 
-
+int CWindowCanvas::get_clear_color()
+{
+       int color = mwindow->edl->session->cwindow_clear_color;
+       if( color < 0 ) color = get_canvas()->get_bg_color();
+       return color;
+}