blade and hard egdes, undo cache reset bug, sams ladspa icons, theme image access...
[goodguy/history.git] / cinelerra-5.1 / cinelerra / trackcanvas.C
index a0ba9f27a4c406391329bb31d50d85c5719ef855..00ca2b6392588eb75c9f2be0085f630100ffae4f 100644 (file)
@@ -26,7 +26,7 @@
 #include "bcsignals.h"
 #include "bctimer.h"
 #include "clip.h"
-#include "colors.h"
+#include "bccolors.h"
 #include "cplayback.h"
 #include "cursors.h"
 #include "cwindowgui.h"
@@ -46,6 +46,7 @@
 #include "keyframepopup.h"
 #include "keyframes.h"
 #include "keys.h"
+#include "labels.h"
 #include "localsession.h"
 #include "mainclock.h"
 #include "maincursor.h"
@@ -109,6 +110,7 @@ TrackCanvas::TrackCanvas(MWindow *mwindow,
        render_timer = new Timer;
        hourglass_enabled = 0;
        timebar_position = -1;
+       snapped = 0;
 }
 
 TrackCanvas::~TrackCanvas()
@@ -1594,7 +1596,7 @@ void TrackCanvas::draw_plugins()
        char string[BCTEXTLEN];
        int current_on = 0;
        int current_show = 0;
-
+       int current_preset = 0;
 
 //     if(!mwindow->edl->session->show_assets) goto done;
 
@@ -1602,6 +1604,8 @@ void TrackCanvas::draw_plugins()
                plugin_on_toggles.values[i]->in_use = 0;
        for(int i = 0; i < plugin_show_toggles.total; i++)
                plugin_show_toggles.values[i]->in_use = 0;
+       for(int i = 0; i < preset_edit_buttons.total; i++)
+               plugin_show_toggles.values[i]->in_use = 0;
 
 
        for(Track *track = mwindow->edl->tracks->first;
@@ -1709,9 +1713,21 @@ void TrackCanvas::draw_plugins()
                                                                }
                                                                current_show++;
                                                        }
-
-
-
+                                                       toggle_x -= PluginPresetEdit::calculate_w(mwindow) + 10;
+                                                       if(toggle_x > min_x)
+                                                       {
+                                                               if(current_preset >= preset_edit_buttons.total)
+                                                               {
+                                                                       PluginPresetEdit *preset_edit = new PluginPresetEdit(mwindow, toggle_x, toggle_y, plugin);
+                                                                       add_subwindow(preset_edit);
+                                                                       preset_edit_buttons.append(preset_edit);
+                                                               }
+                                                               else
+                                                               {
+                                                                       preset_edit_buttons.values[current_preset]->update(toggle_x, toggle_y, plugin);
+                                                               }
+                                                               current_preset++;
+                                                       }
                                                }
                                        }
                                }
@@ -1721,6 +1737,10 @@ void TrackCanvas::draw_plugins()
 
 // Remove unused toggles
 
+       while(current_preset < preset_edit_buttons.total)
+       {
+               preset_edit_buttons.remove_object_number(current_preset);
+       }
        while(current_show < plugin_show_toggles.total)
        {
                plugin_show_toggles.remove_object_number(current_show);
@@ -1730,7 +1750,6 @@ void TrackCanvas::draw_plugins()
        {
                plugin_on_toggles.remove_object_number(current_on);
        }
-
 }
 
 void TrackCanvas::refresh_plugintoggles()
@@ -1745,6 +1764,41 @@ void TrackCanvas::refresh_plugintoggles()
                PluginShow *show = plugin_show_toggles.values[i];
                show->reposition_window(show->get_x(), show->get_y());
        }
+       for(int i = 0; i < preset_edit_buttons.total; i++)
+       {
+               PluginPresetEdit *preset_edit = preset_edit_buttons.values[i];
+               preset_edit->reposition_window(preset_edit->get_x(), preset_edit->get_y());
+       }
+}
+
+void TrackCanvas::draw_hard_edges()
+{
+       int64_t x, y, w, h;
+
+//     if(!mwindow->edl->session->show_assets) return;
+
+       for(Track *track = mwindow->edl->tracks->first; track; track = track->next) {
+               for(Edit *edit = track->edits->first; edit; edit = edit->next) {
+                       if( !edit->hard_left && !edit->hard_right ) continue;
+                       edit_dimensions(edit, x, y, w, h);
+                       set_color(GREEN);
+                       set_opaque();    int y1 = y+h-1;
+                       if( edit->hard_left ) {
+                               ArrayList<int> xpt, ypt;
+                               xpt.append(x);              ypt.append(y1);
+                               xpt.append(x+HANDLE_W);     ypt.append(y1);
+                               xpt.append(x);              ypt.append(y1-HANDLE_H);
+                               fill_polygon(&xpt, &ypt);
+                       }
+                       if( edit->hard_right ) {
+                               ArrayList<int> xpt, ypt;   int x1 = x+w-1;
+                               xpt.append(x1);            ypt.append(y1);
+                               xpt.append(x1-HANDLE_W);   ypt.append(y1);
+                               xpt.append(x1);            ypt.append(y1-HANDLE_H);
+                               fill_polygon(&xpt, &ypt);
+                       }
+               }
+       }
 }
 
 void TrackCanvas::draw_inout_points()
@@ -1763,7 +1817,7 @@ void TrackCanvas::draw_drag_handle()
                        mwindow->edl->local_session->zoom_sample -
                        mwindow->edl->local_session->view_start[pane->number]);
 //printf("TrackCanvas::draw_drag_handle 2 %d %jd\n", pane->number, pixel1);
-               set_color(GREEN);
+               set_color(!snapped ? GREEN : (snapped=0, YELLOW));
                set_inverse();
 //printf("TrackCanvas::draw_drag_handle 3\n");
                draw_line(pixel1, 0, pixel1, get_h());
@@ -3418,6 +3472,7 @@ void TrackCanvas::draw_overlays()
 
 // Plugins
        draw_plugins();
+       draw_hard_edges();
 
 // Loop points
        draw_loop_points();
@@ -3472,15 +3527,46 @@ int TrackCanvas::deactivate()
 void TrackCanvas::update_drag_handle()
 {
        double new_position;
+       int cursor_x = get_cursor_x();
 
        new_position =
-               (double)(get_cursor_x() +
+               (double)(cursor_x +
                mwindow->edl->local_session->view_start[pane->number]) *
                mwindow->edl->local_session->zoom_sample /
                mwindow->edl->session->sample_rate;
+
        new_position =
                mwindow->edl->align_to_frame(new_position, 0);
 
+       if( ctrl_down() && alt_down() ) {
+#define snapper(v) do { \
+       double pos = (v); \
+       if( pos < 0 ) break; \
+       double dist = fabs(new_position - pos); \
+       if( dist >= snap_min ) break; \
+       snap_position = pos;  snap_min = dist; \
+} while(0)
+               double snap_position = new_position;
+               double snap_min = DBL_MAX;
+               if( mwindow->edl->local_session->inpoint_valid() )
+                       snapper(mwindow->edl->local_session->get_inpoint());
+               if( mwindow->edl->local_session->outpoint_valid() )
+                       snapper(mwindow->edl->local_session->get_outpoint());
+               snapper(mwindow->edl->prev_edit(new_position));
+               snapper(mwindow->edl->next_edit(new_position));
+               Label *prev_label = mwindow->edl->labels->prev_label(new_position);
+               if( prev_label ) snapper(prev_label->position);
+               Label *next_label = mwindow->edl->labels->next_label(new_position);
+               if( next_label ) snapper(next_label->position);
+               int snap_x = snap_position * mwindow->edl->session->sample_rate /
+                       mwindow->edl->local_session->zoom_sample -
+                       mwindow->edl->local_session->view_start[pane->number];
+               if( abs(snap_x - cursor_x) < HANDLE_W ) {
+                       snapped = 1;
+                       new_position = snap_position;
+               }
+#undef snapper
+       }
 
        if(new_position != mwindow->session->drag_position)
        {
@@ -4246,53 +4332,58 @@ int TrackCanvas::do_edit_handles(int cursor_x, int cursor_y, int button_press,
        int &rerender, int &update_overlay, int &new_cursor, int &update_cursor)
 {
        Edit *edit_result = 0;
-       int handle_result = 0;
+       int handle_result = -1;
        int result = 0;
 
-       if(!mwindow->edl->session->show_assets) return 0;
+       if( !mwindow->edl->session->show_assets ) return 0;
 
-       for(Track *track = mwindow->edl->tracks->first;
-               track && !result;
-               track = track->next) {
-               for(Edit *edit = track->edits->first;
-                       edit && !result;
-                       edit = edit->next) {
+       for( Track *track=mwindow->edl->tracks->first; track && !result; track=track->next) {
+               for( Edit *edit=track->edits->first; edit && !result; edit=edit->next ) {
                        int64_t edit_x, edit_y, edit_w, edit_h;
                        edit_dimensions(edit, edit_x, edit_y, edit_w, edit_h);
 
-                       if(cursor_x >= edit_x && cursor_x <= edit_x + edit_w &&
-                               cursor_y >= edit_y && cursor_y < edit_y + edit_h) {
-                               if(cursor_x < edit_x + HANDLE_W) {
+                       if( cursor_x >= edit_x && cursor_x <= edit_x + edit_w &&
+                               cursor_y >= edit_y && cursor_y < edit_y + edit_h ) {
+                               if( cursor_x < edit_x + HANDLE_W ) {
                                        edit_result = edit;
                                        handle_result = 0;
-                                       result = 1;
+                                       if( cursor_y >= edit_y+edit_h - HANDLE_W ) {
+                                               new_cursor = DOWNLEFT_RESIZE;
+                                               if( button_press == LEFT_BUTTON )
+                                                       result = -1;
+                                       }
+                                       else
+                                               result = 1;
                                }
-                               else if(cursor_x >= edit_x + edit_w - HANDLE_W) {
+                               else if( cursor_x >= edit_x + edit_w - HANDLE_W ) {
                                        edit_result = edit;
                                        handle_result = 1;
-                                       result = 1;
-                               }
-                               else {
-                                       result = 0;
+                                       if( cursor_y >= edit_y+edit_h - HANDLE_W ) {
+                                               new_cursor = DOWNRIGHT_RESIZE;
+                                               if( button_press == LEFT_BUTTON )
+                                                       result = -1;
+                                       }
+                                       else
+                                               result = 1;
                                }
                        }
                }
        }
 
        update_cursor = 1;
-       if(result) {
+       if( result > 0 ) {
                double position = 0;
-               if(handle_result == 0) {
+               if( handle_result == 0 ) {
                        position = edit_result->track->from_units(edit_result->startproject);
                        new_cursor = LEFT_CURSOR;
                }
-               else if(handle_result == 1) {
+               else if( handle_result == 1 ) {
                        position = edit_result->track->from_units(edit_result->startproject + edit_result->length);
                        new_cursor = RIGHT_CURSOR;
                }
 
 // Reposition cursor
-               if(button_press) {
+               if( button_press ) {
                        mwindow->session->drag_edit = edit_result;
                        mwindow->session->drag_handle = handle_result;
                        mwindow->session->drag_button = get_buttonpress() - 1;
@@ -4306,6 +4397,43 @@ int TrackCanvas::do_edit_handles(int cursor_x, int cursor_y, int button_press,
                        update_overlay = 1;
                }
        }
+       else if( result <  0) {
+               mwindow->undo->update_undo_before();
+               if( !shift_down() ) {
+                       if( handle_result == 0 )
+                               edit_result->hard_left = !edit_result->hard_left;
+                       else if( handle_result == 1 )
+                               edit_result->hard_right = !edit_result->hard_right;
+               }
+               else {
+                       int status = handle_result == 0 ? edit_result->hard_left :
+                                    handle_result == 1 ? edit_result->hard_right : 0;
+                       int new_status = !status;
+                       int64_t edit_edge = edit_result->startproject;
+                       if( handle_result == 1 ) edit_edge += edit_result->length;
+                       double edge_position = edit_result->track->from_units(edit_edge);
+                       for( Track *track=mwindow->edl->tracks->first; track!=0; track=track->next ) {
+                               int64_t track_position = track->to_units(edge_position, 1);
+                               Edit *left_edit = track->edits->editof(track_position, PLAY_FORWARD, 0);
+                               if( left_edit ) {
+                                       int64_t left_edge = left_edit->startproject;
+                                       double left_position = track->from_units(left_edge);
+                                       if( EQUIV(edge_position, left_position) )
+                                               left_edit->hard_left = new_status;
+                               }
+                               Edit *right_edit = track->edits->editof(track_position, PLAY_REVERSE, 0);
+                               if( right_edit ) {
+                                       int64_t right_edge = right_edit->startproject + right_edit->length;
+                                       double right_position = track->from_units(right_edge);
+                                       if( EQUIV(edge_position, right_position) )
+                                               right_edit->hard_right = new_status;
+                               }
+                       }
+               }
+               rerender = update_overlay = 1;
+               mwindow->undo->update_undo_after(_("hard_edge"), LOAD_EDITS);
+               result = 1;
+       }
 
        return result;
 }
@@ -4398,7 +4526,7 @@ int TrackCanvas::do_tracks(int cursor_x, int cursor_y, int button_press)
                int64_t track_x, track_y, track_w, track_h;
                track_dimensions(track, track_x, track_y, track_w, track_h);
 
-               if(button_press && get_buttonpress() == 3 &&
+               if(button_press && get_buttonpress() == RIGHT_BUTTON &&
                        cursor_y >= track_y && cursor_y < track_y + track_h) {
                        gui->edit_menu->update(track, 0);
                        gui->edit_menu->activate_menu();
@@ -4474,10 +4602,10 @@ int TrackCanvas::do_edits(int cursor_x, int cursor_y, int button_press, int drag
                                                        mwindow->edl->local_session->zoom_sample /
                                                        mwindow->edl->session->sample_rate;
 
+                                               int cx, cy;
+                                               get_abs_cursor(cx, cy);
                                                gui->drag_popup = new BC_DragWindow(gui,
-                                                       mwindow->theme->get_image("clip_icon") /*,
-                                                       get_abs_cursor_x(0) - mwindow->theme->get_image("clip_icon")->get_w() / 2,
-                                                       get_abs_cursor_y(0) - mwindow->theme->get_image("clip_icon")->get_h() / 2 */);
+                                                       mwindow->theme->get_image("clip_icon"), cx, cy);
 
                                                result = 1;
                                        }
@@ -4586,19 +4714,18 @@ int TrackCanvas::do_plugins(int cursor_x, int cursor_y, int drag_start,
                                                        frame = mwindow->theme->get_image("veffect_icon");
                                                }
                                        }
-
-                                       gui->drag_popup = new BC_DragWindow(gui, frame /*,
-                                               get_abs_cursor_x(0) - frame->get_w() / 2,
-                                               get_abs_cursor_y(0) - frame->get_h() / 2 */);
+                                       int cx, cy;
+                                       get_abs_cursor(cx, cy);
+                                       gui->drag_popup = new BC_DragWindow(gui, frame, cx, cy);
                                                break; }
 
                                case PLUGIN_SHAREDPLUGIN:
-                               case PLUGIN_SHAREDMODULE:
-                                       gui->drag_popup = new BC_DragWindow(gui,
-                                               mwindow->theme->get_image("clip_icon") /*,
-                                               get_abs_cursor_x(0) - mwindow->theme->get_image("clip_icon")->get_w() / 2,
-                                               get_abs_cursor_y(0) - mwindow->theme->get_image("clip_icon")->get_h() / 2 */);
-                                       break;
+                               case PLUGIN_SHAREDMODULE: {
+                                       VFrame *frame = mwindow->theme->get_image("clip_icon");
+                                       int cx, cy;
+                                       get_abs_cursor(cx, cy);
+                                       gui->drag_popup = new BC_DragWindow(gui, frame, cx, cy);
+                                       break; }
                                }
 
                                result = 1;
@@ -4658,7 +4785,6 @@ int TrackCanvas::button_press_event()
        int result = 0;
        int cursor_x, cursor_y;
        int new_cursor;
-       double start_position = mwindow->edl->local_session->get_selectionstart(1);
 
        cursor_x = get_cursor_x();
        cursor_y = get_cursor_y();
@@ -4815,23 +4941,7 @@ int TrackCanvas::button_press_event()
                        gui->flash_canvas(1);
                }
        }
-// if snapping to selection point
-       if( gui->ctrl_down() && gui->alt_down() ) {
-               switch( mwindow->session->current_operation ) {
-               case DRAG_EDITHANDLE1:
-                       mwindow->session->drag_position = start_position;
-                       mwindow->session->current_operation = NO_OPERATION;
-                       drag_scroll = 0;
-                       end_edithandle_selection();
-                       break;
-               case DRAG_PLUGINHANDLE1:
-                       mwindow->session->drag_position = start_position;
-                       mwindow->session->current_operation = NO_OPERATION;
-                       drag_scroll = 0;
-                       end_pluginhandle_selection();
-                       break;
-               }
-       }
+
        return result;
 }